diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index eabdf128ecad3f207991af29cc569d9309305fcc..2e7260c229930127af913f4ef75f0f0e08d58573 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -7,6 +7,10 @@ stages: - step-D - step-E - step-F + - post-deploy + - test + + # List global variables variables: @@ -38,8 +42,6 @@ variables: # general Ubuntu job template .ubuntu-template-job-base: &ubuntu-job-base image: ubuntu:22.04 - tags: - - docker rules: - when: always @@ -51,13 +53,11 @@ variables: .ubuntu-template-job-default: &ubuntu-job <<: *ubuntu-job-base before_script: - - apt-get update -qq && apt-get install -y -qq git wget unzip build-essential freeglut3-dev libboost-all-dev qtbase5-dev libqt5opengl5-dev mercurial libeigen3-dev libsqlite3-dev nlohmann-json3-dev libexpat1-dev libxerces-c-dev libhdf5-dev libhepmc3-dev cmake + - apt-get update -qq && apt-get install -y -qq apt-utils git wget unzip build-essential freeglut3-dev libboost-all-dev qtbase5-dev libqt5opengl5-dev mercurial libeigen3-dev libsqlite3-dev nlohmann-json3-dev libexpat1-dev libxerces-c-dev libhdf5-dev libhepmc3-dev cmake # .ubuntu-template-job-registry: &ubuntu-job-registry # image: gitlab-registry.cern.ch/mbandier/geant4-ubuntu/base-image:1.1 -# tags: -# - docker # before_script: # - apt-get update -qq && apt-get install -y -qq libeigen3-dev libsqlite3-dev @@ -80,6 +80,7 @@ variables: artifacts: paths: - install + expire_in: 1 day .soqt-build-template: &soqt-job variables: @@ -100,6 +101,7 @@ variables: artifacts: paths: - install + expire_in: 1 day @@ -124,6 +126,7 @@ variables: artifacts: paths: - install + expire_in: 1 day @@ -151,6 +154,7 @@ variables: artifacts: paths: - install + expire_in: 1 day @@ -179,87 +183,96 @@ debug-job: # Thus, for our macOS pipeline, we use 'brew bundle' to check and install all needed # dependencies, which are listed in a custom Brewfile under the CI folder. -mac-coin: - <<: *macos-job - <<: *coin-job - stage: step-A - - -mac-soqt: - <<: *macos-job - <<: *soqt-job - stage: step-B - needs: ["mac-coin"] +# mac-coin: +# <<: *macos-job +# <<: *coin-job +# stage: step-A +# mac-soqt: +# <<: *macos-job +# <<: *soqt-job +# stage: step-B +# needs: ["mac-coin"] +# mac-gm: +# <<: *macos-job +# <<: *geomodel-job +# stage: step-A -mac-gm: - <<: *macos-job - <<: *geomodel-job - stage: step-A - - -mac-gm-tools: - <<: *macos-job - <<: *geomodel-job - stage: step-A - variables: - CMAKE_ARGS: ${CMAKE_BASE_ARGS} - CMAKE_EXTRA_FLAGS: -DGEOMODEL_BUILD_TOOLS=TRUE - - -mac-gm-visualization: - <<: *macos-job - <<: *geomodel-job - stage: step-C - needs: ["mac-coin", "mac-soqt"] - variables: - CMAKE_ARGS: ${CMAKE_BASE_ARGS} - CMAKE_EXTRA_FLAGS: -DGEOMODEL_BUILD_VISUALIZATION=TRUE - +# mac-gm-tools: +# <<: *macos-job +# <<: *geomodel-job +# stage: step-A +# variables: +# CMAKE_ARGS: ${CMAKE_BASE_ARGS} +# CMAKE_EXTRA_FLAGS: -DGEOMODEL_BUILD_TOOLS=TRUE -mac-gm-examples: - <<: *macos-job - <<: *geomodel-job - stage: step-A - # needs: ["mac-config"] - variables: - CMAKE_ARGS: ${CMAKE_BASE_ARGS} - CMAKE_CONFIG_FLAGS: -DGEOMODEL_BUILD_EXAMPLES=TRUE +# mac-gm-visualization: +# <<: *macos-job +# <<: *geomodel-job +# stage: step-C +# needs: ["mac-coin", "mac-soqt"] +# variables: +# CMAKE_ARGS: ${CMAKE_BASE_ARGS} +# CMAKE_EXTRA_FLAGS: -DGEOMODEL_BUILD_VISUALIZATION=TRUE -mac-gm-gmg4: - <<: *macos-job - <<: *geomodel-job - stage: step-A - variables: - CMAKE_ARGS: ${CMAKE_BASE_ARGS} - CMAKE_CONFIG_FLAGS: -DGEOMODEL_BUILD_GEOMODELG4=TRUE +# mac-gm-examples: +# <<: *macos-job +# <<: *geomodel-job +# stage: step-A +# # needs: ["mac-config"] +# variables: +# CMAKE_ARGS: ${CMAKE_BASE_ARGS} +# CMAKE_CONFIG_FLAGS: -DGEOMODEL_BUILD_EXAMPLES=TRUE +# mac-gm-gmg4: +# <<: *macos-job +# <<: *geomodel-job +# stage: step-A +# variables: +# CMAKE_ARGS: ${CMAKE_BASE_ARGS} +# CMAKE_CONFIG_FLAGS: -DGEOMODEL_BUILD_GEOMODELG4=TRUE -mac-gm-examples-gmg4: - <<: *macos-job - <<: *geomodel-job - stage: step-A - variables: - CMAKE_ARGS: ${CMAKE_BASE_ARGS} - CMAKE_CONFIG_FLAGS: -DGEOMODEL_BUILD_EXAMPLES_W_GEANT4=TRUE +# mac-gm-examples-gmg4: +# <<: *macos-job +# <<: *geomodel-job +# stage: step-A +# variables: +# CMAKE_ARGS: ${CMAKE_BASE_ARGS} +# CMAKE_CONFIG_FLAGS: -DGEOMODEL_BUILD_EXAMPLES_W_GEANT4=TRUE +# mac-gm-fullsimlight: +# <<: *macos-job +# <<: *geomodel-job +# stage: step-A +# variables: +# CMAKE_ARGS: ${CMAKE_BASE_ARGS} +# CMAKE_CONFIG_FLAGS: -DGEOMODEL_BUILD_FULLSIMLIGHT=TRUE -mac-gm-fullsimlight: - <<: *macos-job - <<: *geomodel-job - stage: step-A - variables: - CMAKE_ARGS: ${CMAKE_BASE_ARGS} - CMAKE_CONFIG_FLAGS: -DGEOMODEL_BUILD_FULLSIMLIGHT=TRUE +# mac-gm-fsl: +# <<: *macos-job +# <<: *geomodel-job +# stage: step-A +# variables: +# CMAKE_ARGS: ${CMAKE_BASE_ARGS} +# CMAKE_EXTRA_FLAGS: -DGEOMODEL_BUILD_FSL=TRUE -mac-gm-atlasextras: - <<: *macos-job - <<: *geomodel-job - stage: step-A - variables: - CMAKE_ARGS: ${CMAKE_BASE_ARGS} - CMAKE_CONFIG_FLAGS: -DGEOMODEL_BUILD_ATLASEXTENSIONS=TRUE +# mac-gm-all: +# <<: *macos-job +# <<: *geomodel-job +# stage: step-C +# needs: ["mac-coin", "mac-soqt"] +# variables: +# CMAKE_ARGS: ${CMAKE_BASE_ARGS} +# CMAKE_EXTRA_FLAGS: -DGEOMODEL_BUILD_ALL=TRUE + +# mac-gm-atlasextras: +# <<: *macos-job +# <<: *geomodel-job +# stage: step-A +# variables: +# CMAKE_ARGS: ${CMAKE_BASE_ARGS} +# CMAKE_CONFIG_FLAGS: -DGEOMODEL_BUILD_ATLASEXTENSIONS=TRUE ### UBUNTU ALL-IN-ONE BUILD JOBS @@ -347,6 +360,31 @@ ubu-gm-fullsimlight: CMAKE_ARGS: ${CMAKE_BASE_ARGS} CMAKE_CONFIG_FLAGS: -DGEOMODEL_BUILD_FULLSIMLIGHT=TRUE + +ubu-gm-fsl: + <<: *ubuntu-job + <<: *geomodel-job + stage: step-B + needs: ["ubu-geant4"] + variables: + CMAKE_ARGS: ${CMAKE_BASE_ARGS} + CMAKE_CONFIG_FLAGS: -DGEOMODEL_BUILD_FSL=TRUE + + +ubu-gm-all: + <<: *ubuntu-job + <<: *geomodel-job + stage: step-C + needs: ["ubu-coin", "ubu-soqt", "ubu-geant4"] + variables: + CMAKE_ARGS: ${CMAKE_BASE_ARGS} + CMAKE_CONFIG_FLAGS: -DGEOMODEL_BUILD_ALL=TRUE + artifacts: + paths: + - build + expire_in: 30 minutes + + ubu-gm-atlasextras: <<: *ubuntu-job <<: *geomodel-job @@ -396,6 +434,7 @@ ubu-single-gmbase: artifacts: paths: - install + expire_in: 1 day ubu-single-gmtools: <<: *ubuntu-job @@ -412,6 +451,7 @@ ubu-single-gmtools: artifacts: paths: - install + expire_in: 1 day ubu-single-gmviz: <<: *ubuntu-job @@ -428,6 +468,7 @@ ubu-single-gmviz: artifacts: paths: - install + expire_in: 1 day ubu-single-gmg4: <<: *ubuntu-job @@ -444,6 +485,7 @@ ubu-single-gmg4: artifacts: paths: - install + expire_in: 1 day ubu-single-gmfullsimlight: <<: *ubuntu-job @@ -460,6 +502,7 @@ ubu-single-gmfullsimlight: artifacts: paths: - install + expire_in: 1 day ubu-single-gmfsl: <<: *ubuntu-job @@ -473,9 +516,6 @@ ubu-single-gmfsl: - cmake ${CMAKE_ARGS} ../FSL # the CMAKE_EXTRA_FLAGS are set by specific jobs when needed - cmake --build . -- -j2 - cmake --build . -- install - artifacts: - paths: - - install ##################### @@ -518,9 +558,11 @@ docs-deploy: stage: step-B needs: ["docs-build"] rules: - - if: '$CI_COMMIT_BRANCH == "master"' # Deploy, only if changes are pushed to master. + - if: '$CI_COMMIT_BRANCH == "main"' # Deploy, only if changes are pushed to main. changes: - documentation/**/* + allow_failure: true + timeout: 30 minutes variables: "EOS_PATH": "/eos/project/g/geomodel/www/home" image: gitlab-registry.cern.ch/ci-tools/ci-web-deployer:latest @@ -535,80 +577,126 @@ docs-deploy: ##################### ### Docker images ### ##################### +## New build jobs for Docker images based on Dockerfiles +## It uses the new CERN Kaniko infrastructure +## See: +## - https://gitlab.cern.ch/gitlabci-examples/build_docker_image/-/blob/master/.gitlab-ci.yml#L11-27 +## --- -## Build a 'base' Docker image -## containing the GeoModel base packages -## Note: we build the docker image only from 'master' and tags -build_system_docker: +# Build the 'base' image containing the system packages +## Note: +## - we build the docker image only from 'main' and tags +## - image's final name is, e.g., "geomodel:main-base" +build_docker_system: stage: step-A only: refs: - - master + - main - tags variables: - TO: $CI_REGISTRY_IMAGE:${CI_COMMIT_REF_NAME}-base - DOCKER_FILE: 'CI/DockerfileBase' + # To push to a specific docker tag other than latest(the default), amend the --destination parameter, e.g. --destination $CI_REGISTRY_IMAGE:$CI_BUILD_REF_NAME + # See https://docs.gitlab.com/ee/ci/variables/predefined_variables.html#variables-reference for available variables + IMAGE_DESTINATION: ${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_NAME}-base + # === Git-related variables # all submodules will be cloned recursively upon start of CI job GIT_SUBMODULE_STRATEGY: recursive GIT_SSL_NO_VERIFY: "true" - tags: - - docker-image-build + image: + # The kaniko debug image is recommended because it has a shell, and a shell is required for an image to be used with GitLab CI/CD. + name: gcr.io/kaniko-project/executor:debug + entrypoint: [""] script: - - ignore - -## Construct one Docker image containing -## also Geant4 + # Prepare Kaniko configuration file + - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json + # Build and push the image from the Dockerfile at the root of the project. + - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/CI/DockerfileBase --destination $IMAGE_DESTINATION + # Print the full registry path of the pushed image + - echo "Image pushed successfully to ${IMAGE_DESTINATION}" + +## Build a Docker image containing Geant4, too +## (a quite large image, then!) ## Note: -## - we build the docker image only from 'master' and tags -## - image's final name is, e.g., "geomodel:master-base" +## - we build the docker image only from 'main' and tags +## - image's final name is, e.g., "geomodel:main-full" ## -build_full_docker: +build_docker_full: stage: step-B allow_failure: true + needs: + - build_docker_system + timeout: 2h 0m only: refs: - - master + - main - tags variables: - TO: $CI_REGISTRY_IMAGE:${CI_COMMIT_REF_NAME}-full - DOCKER_FILE: 'CI/DockerfileFull' + # To push to a specific docker tag other than latest(the default), amend the --destination parameter, e.g. --destination $CI_REGISTRY_IMAGE:$CI_BUILD_REF_NAME + # See https://docs.gitlab.com/ee/ci/variables/predefined_variables.html#variables-reference for available variables + IMAGE_DESTINATION: ${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_NAME}-full + # === Git-related variables # all submodules will be cloned recursively upon start of CI job GIT_SUBMODULE_STRATEGY: recursive GIT_SSL_NO_VERIFY: "true" - BUILD_ARG: BASEIMAGE=$CI_REGISTRY_IMAGE:${CI_COMMIT_REF_NAME}-base - tags: - - docker-image-build + image: + # The kaniko debug image is recommended because it has a shell, and a shell is required for an image to be used with GitLab CI/CD. + name: gcr.io/kaniko-project/executor:debug + entrypoint: [""] script: - - ignore - needs: - - build_system_docker - timeout: 2h 0m - -## Construct one Docker image only for -## viewer puposes + # Prepare Kaniko configuration file + - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json + # Build and push the image from the Dockerfile at the root of the project. + - /kaniko/executor + --context $CI_PROJECT_DIR + --dockerfile $CI_PROJECT_DIR/CI/DockerfileFull + --destination $IMAGE_DESTINATION + --build-arg "BASEIMAGE=$CI_REGISTRY_IMAGE:${CI_COMMIT_REF_NAME}-base" + # Print the full registry path of the pushed image + - echo "Image pushed successfully to ${IMAGE_DESTINATION}" + +## Build a Docker image for visualization pupose. +## This image does not contain +## FullSimLight or other Geant4-related packages. ## Note: -## - we build the docker image only from 'master' and tags -## - image's final name is, e.g., "geomodel:master-light" +## - we build the docker image only from 'main' and tags +## - image's final name is, e.g., "geomodel:main-light" ## -build_light_docker: +build_docker_light: stage: step-B + allow_failure: true + needs: + - build_docker_system + timeout: 2h 0m only: refs: - - master + - main - tags variables: - TO: $CI_REGISTRY_IMAGE:${CI_COMMIT_REF_NAME}-light - DOCKER_FILE: 'CI/DockerfileLight' + # To push to a specific docker tag other than latest(the default), amend the --destination parameter, e.g. --destination $CI_REGISTRY_IMAGE:$CI_BUILD_REF_NAME + # See https://docs.gitlab.com/ee/ci/variables/predefined_variables.html#variables-reference for available variables + IMAGE_DESTINATION: ${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_NAME}-light + # === Git-related variables # all submodules will be cloned recursively upon start of CI job GIT_SUBMODULE_STRATEGY: recursive GIT_SSL_NO_VERIFY: "true" - BUILD_ARG: BASEIMAGE=$CI_REGISTRY_IMAGE:${CI_COMMIT_REF_NAME}-base - tags: - - docker-image-build + image: + # The kaniko debug image is recommended because it has a shell, and a shell is required for an image to be used with GitLab CI/CD. + name: gcr.io/kaniko-project/executor:debug + entrypoint: [""] script: - - ignore - needs: - - build_system_docker + # Prepare Kaniko configuration file + - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json + # Build and push the image from the Dockerfile at the root of the project. + - /kaniko/executor + --context $CI_PROJECT_DIR + --dockerfile $CI_PROJECT_DIR/CI/DockerfileLight + --destination $IMAGE_DESTINATION + --build-arg "BASEIMAGE=$CI_REGISTRY_IMAGE:${CI_COMMIT_REF_NAME}-base" + # Print the full registry path of the pushed image + - echo "Image pushed successfully to ${IMAGE_DESTINATION}" + + + + ########## ## TAGS ## @@ -631,3 +719,34 @@ after-tag-creation: - test "$TAG" != "$VERSION" && echo "ERROR --> There is a TAG/VERSION mismatch" && exit 1 - echo "OK." + + +########### +# A special job, only meant to change the default expiry policy +# from '1day' to 'never' for jobs which run on 'tags'. +# This is done to keep the artifacts from tags indefinitely, +# while deleting all the others. +########## +persist-tag-artifacts: + # Use this job to specify artifacts that should never expire for tag pipelines. + stage: post-deploy + rules: + - if: '$CI_COMMIT_TAG != null' + script: + - echo "Persisting artifacts for tag pipelines" + artifacts: + # Specify artifacts from previous jobs to be persisted indefinitely + paths: + - install + expire_in: never + + +tests-ubuntu: + <<: *ubuntu-job + stage: step-test + needs: ["ubu-gm-all"] + stage: test + script: + - cd build + - ctest #--output-on-failure + diff --git a/CI/DockerfileFull b/CI/DockerfileFull index e9116212f41dab6698a976db1329c351b60cfdba..1ce4c350ce77d8f811c8e5404bda8d454ed0081d 100755 --- a/CI/DockerfileFull +++ b/CI/DockerfileFull @@ -1,5 +1,5 @@ # Setup the most basic image -ARG BASEIMAGE=gitlab-registry.cern.ch/geomodeldev/geomodel:master-base +ARG BASEIMAGE=gitlab-registry.cern.ch/geomodeldev/geomodel:main-base FROM ${BASEIMAGE} diff --git a/CI/DockerfileLight b/CI/DockerfileLight index ead60ce9bdbc487593da3b9ab016d28dd2db547b..3434338f00317159b24f29be493022b1eeb2f25e 100644 --- a/CI/DockerfileLight +++ b/CI/DockerfileLight @@ -1,5 +1,5 @@ # Setup the most basic image -ARG BASEIMAGE=gitlab-registry.cern.ch/geomodeldev/geomodel:master-base +ARG BASEIMAGE=gitlab-registry.cern.ch/geomodeldev/geomodel:main-base FROM ${BASEIMAGE} COPY . /workdir/GeoModel_src/ diff --git a/CI/gitlab_api_examples.md b/CI/gitlab_api_examples.md index a6420355cb8dd3473600169542d254d3938af4b4..fdea33b9a6ef987b75f0916f09678e30289225c7 100644 --- a/CI/gitlab_api_examples.md +++ b/CI/gitlab_api_examples.md @@ -3,7 +3,9 @@ **NOTE:** Here below, `95156` is the ID of the GeoModel project on the CERN GitLab installation. You can find the ID of your project by looking at the main page of your GitLab repository, you'll find the ID under the name of the repository. **NOTE:** Being the GeoModel respoitory public, we don't need authorization. If your project is not public, you need to pass a variable in the header. Please [see this post](https://stackoverflow.com/a/59949488/320369) for an example. +But please notice, to get CI **jobs** through the API, you need at least a Personal Access Token, even if the repository is fully public. +[TOC] ## Tags @@ -41,22 +43,22 @@ The answer is: ... ``` -Get only the pipelines for branch `master`: +Get only the pipelines for branch `main`: ``` -curl "https://gitlab.cern.ch/api/v4/projects/95156/pipelines?ref=master" +curl "https://gitlab.cern.ch/api/v4/projects/95156/pipelines?ref=main" ``` -Get only the pipelines for branch `master` and with status `success`: +Get only the pipelines for branch `main` and with status `success`: ``` -curl "https://gitlab.cern.ch/api/v4/projects/95156/pipelines?ref=master&status=success" +curl "https://gitlab.cern.ch/api/v4/projects/95156/pipelines?ref=main&status=success" ``` Get the latest successful pipeline, just the latest one: ``` -curl -v -H "Content-Type: application/json" "https://gitlab.cern.ch/api/v4/projects/95156/pipelines?ref=master&status=success&per_page=1&page=1" +curl -v -H "Content-Type: application/json" "https://gitlab.cern.ch/api/v4/projects/95156/pipelines?ref=main&status=success&per_page=1&page=1" ``` To get the JSON content from the curl response, you can use `jq`, the JSON processor. On macOS, you can install `jq` with Homebrew: `brew install jq`. @@ -64,10 +66,168 @@ To get the JSON content from the curl response, you can use `jq`, the JSON proce For example, get the `web_url` link for the latest successful pipeline: ``` -curl -v -H "Content-Type: application/json" "https://gitlab.cern.ch/api/v4/projects/95156/pipelines?ref=master&status=success&per_page=1&page=1" | jq -r '.[0] | .web_url' +curl -v -H "Content-Type: application/json" "https://gitlab.cern.ch/api/v4/projects/95156/pipelines?ref=main&status=success&per_page=1&page=1" | jq -r '.[0] | .web_url' ``` Then, to get the DAG page from the latest pipeline, just use the link from above and add “dag”: https://gitlab.cern.ch/GeoModelDev/GeoModel/-/pipelines/2163714/dag + +## Get a CI job or list of jobs + + +### Get a single job and its metadata + +We can ask for the latest CI job with: + +```sh +curl -Ss --header "PRIVATE-TOKEN:<token>" "https://gitlab.cern.ch/api/v4/projects/95156/jobs/?page=1&per_page=1" +``` + +this gives: + +``` +[{"id":32216368,"status":"success","stage":"step-E","name":"ubu-single-gmfsl","ref":"main","tag":false,"coverage":null,"allow_failure":false,"created_at":"2023-09-04T18:38:51.723+02:00","started_at":"2023-09-04T19:10:52.976+02:00","finished_at":"2023-09-04T19:14:59.394+02:00","erased_at":null,"duration":246.417715,"queued_duration":0.475744,"user":{"id":281,"username":"rbianchi","name":"Riccardo Maria Bianchi","state":"active","avatar_url":"https://gitlab.cern.ch/uploads/-/system/user/avatar/281/avatar.png","web_url":"https://gitlab.cern.ch/rbianchi","created_at":"2015-04-30T11:00:28.847+02:00","bio":"Particle Physicist (PhD) at CERN working on the ATLAS experiment (since 2005). Faculty Research Associate at the University of Pittsburgh. Co-author of \"Applied Computational Physics\" (Oxford University Press, 2018).","location":"CERN, Geneva, Switzerland","public_email":"riccardo.maria.bianchi@cern.ch","skype":"","linkedin":"riccardo-maria-bianchi-8580432a","twitter":"drric_physics","discord":"","website_url":"www.riccardomariabianchi.com","organization":"ATLAS Experiment, University of Pittsburgh","job_title":"","pronouns":"","bot":false,"work_information":"ATLAS Experiment, University of Pittsburgh","followers":0,"following":0,"local_time":"8:17 PM"},"commit":{"id":"fdafc154d8aa4a8f9f6eefe99d906f623ad99f8a","short_id":"fdafc154","created_at":"2023-09-04T18:38:49.000+02:00","parent_ids":["ffe3884fb7e1a1903fcc17400430137cb12b311e"],"title":"CI: add expiry policy of 1 day to all artifacts","message":"CI: add expiry policy of 1 day to all artifacts\r\n\r\nThis will help the fix of #88","author_name":"Riccardo Maria Bianchi","author_email":"riccardo.maria.bianchi@cern.ch","authored_date":"2023-09-04T18:38:49.000+02:00","committer_name":"Riccardo Maria Bianchi","committer_email":"riccardo.maria.bianchi@cern.ch","committed_date":"2023-09-04T18:38:49.000+02:00","trailers":{},"web_url":"https://gitlab.cern.ch/GeoModelDev/GeoModel/-/commit/fdafc154d8aa4a8f9f6eefe99d906f623ad99f8a"},"pipeline":{"id":6150944,"iid":1561,"project_id":95156,"sha":"fdafc154d8aa4a8f9f6eefe99d906f623ad99f8a","ref":"main","status":"success","source":"push","created_at":"2023-09-04T18:38:51.434+02:00","updated_at":"2023-09-04T19:57:43.438+02:00","web_url":"https://gitlab.cern.ch/GeoModelDev/GeoModel/-/pipelines/6150944"},"web_url":"https://gitlab.cern.ch/GeoModelDev/GeoModel/-/jobs/32216368","project":{"ci_job_token_scope_enabled":false},"artifacts_file":{"filename":"artifacts.zip","size":1381606499},"artifacts":[{"file_type":"archive","size":1381606499,"filename":"artifacts.zip","file_format":"zip"},{"file_type":"metadata","size":995592,"filename":"metadata.gz","file_format":"gzip"},{"file_type":"trace","size":145865,"filename":"job.log","file_format":null}],"runner":{"id":33042,"description":"default-runner-69f5dcf6c6-hsn54","ip_address":"188.185.15.101","active":true,"paused":false,"is_shared":true,"runner_type":"instance_type","name":"gitlab-runner","online":true,"status":"online"},"artifacts_expire_at":"2023-09-05T19:14:48.655+02:00","tag_list":["docker"]}] +``` + +But we can prettify the output with `jq` itself (note teh dot at the end!): + +```sh +curl -Ss --header "PRIVATE-TOKEN:<token>" "https://gitlab.cern.ch/api/v4/projects/95156/jobs/?page=1&per_page=1" | jq . +``` + +which gives this nice output: + +```json +[ + { + "id": 32216368, + "status": "success", + "stage": "step-E", + "name": "ubu-single-gmfsl", + "ref": "main", + "tag": false, + "coverage": null, + "allow_failure": false, + "created_at": "2023-09-04T18:38:51.723+02:00", + "started_at": "2023-09-04T19:10:52.976+02:00", + "finished_at": "2023-09-04T19:14:59.394+02:00", + "erased_at": null, + "duration": 246.417715, + "queued_duration": 0.475744, + "user": { + "id": 281, + "username": "rbianchi", + "name": "Riccardo Maria Bianchi", + "state": "active", + "avatar_url": "https://gitlab.cern.ch/uploads/-/system/user/avatar/281/avatar.png", + "web_url": "https://gitlab.cern.ch/rbianchi", + "created_at": "2015-04-30T11:00:28.847+02:00", + "bio": "Particle Physicist (PhD) at CERN working on the ATLAS experiment (since 2005). Faculty Research Associate at the University of Pittsburgh. Co-author of \"Applied Computational Physics\" (Oxford University Press, 2018).", + "location": "CERN, Geneva, Switzerland", + "public_email": "riccardo.maria.bianchi@cern.ch", + "skype": "", + "linkedin": "riccardo-maria-bianchi-8580432a", + "twitter": "drric_physics", + "discord": "", + "website_url": "www.riccardomariabianchi.com", + "organization": "ATLAS Experiment, University of Pittsburgh", + "job_title": "", + "pronouns": "", + "bot": false, + "work_information": "ATLAS Experiment, University of Pittsburgh", + "followers": 0, + "following": 0, + "local_time": "8:18 PM" + }, + "commit": { + "id": "fdafc154d8aa4a8f9f6eefe99d906f623ad99f8a", + "short_id": "fdafc154", + "created_at": "2023-09-04T18:38:49.000+02:00", + "parent_ids": [ + "ffe3884fb7e1a1903fcc17400430137cb12b311e" + ], + "title": "CI: add expiry policy of 1 day to all artifacts", + "message": "CI: add expiry policy of 1 day to all artifacts\r\n\r\nThis will help the fix of #88", + "author_name": "Riccardo Maria Bianchi", + "author_email": "riccardo.maria.bianchi@cern.ch", + "authored_date": "2023-09-04T18:38:49.000+02:00", + "committer_name": "Riccardo Maria Bianchi", + "committer_email": "riccardo.maria.bianchi@cern.ch", + "committed_date": "2023-09-04T18:38:49.000+02:00", + "trailers": {}, + "web_url": "https://gitlab.cern.ch/GeoModelDev/GeoModel/-/commit/fdafc154d8aa4a8f9f6eefe99d906f623ad99f8a" + }, + "pipeline": { + "id": 6150944, + "iid": 1561, + "project_id": 95156, + "sha": "fdafc154d8aa4a8f9f6eefe99d906f623ad99f8a", + "ref": "main", + "status": "success", + "source": "push", + "created_at": "2023-09-04T18:38:51.434+02:00", + "updated_at": "2023-09-04T19:57:43.438+02:00", + "web_url": "https://gitlab.cern.ch/GeoModelDev/GeoModel/-/pipelines/6150944" + }, + "web_url": "https://gitlab.cern.ch/GeoModelDev/GeoModel/-/jobs/32216368", + "project": { + "ci_job_token_scope_enabled": false + }, + "artifacts_file": { + "filename": "artifacts.zip", + "size": 1381606499 + }, + "artifacts": [ + { + "file_type": "archive", + "size": 1381606499, + "filename": "artifacts.zip", + "file_format": "zip" + }, + { + "file_type": "metadata", + "size": 995592, + "filename": "metadata.gz", + "file_format": "gzip" + }, + { + "file_type": "trace", + "size": 145865, + "filename": "job.log", + "file_format": null + } + ], + "runner": { + "id": 33042, + "description": "default-runner-69f5dcf6c6-hsn54", + "ip_address": "188.185.15.101", + "active": true, + "paused": false, + "is_shared": true, + "runner_type": "instance_type", + "name": "gitlab-runner", + "online": true, + "status": "online" + }, + "artifacts_expire_at": "2023-09-05T19:14:48.655+02:00", + "tag_list": [ + "docker" + ] + } +] +``` + +From the output above it is easy to spot useful metadata to exploit in API calls and scripts! + + +### Get job's metadata + +With `jq` you can extract multiple job's metadata, here's an example of a call that extracts the name of the job and the boolean that says if the job is for a tag or not: + +```sh +curl -Ss --header "PRIVATE-TOKEN:<token>" "https://gitlab.cern.ch/api/v4/projects/95156/jobs/?page=1&per_page=1" | jq -r '.[] | .name + "--" + (.tag|tostring)' + +ubu-single-gmfsl--false +``` diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e520e3f1eee3ebbf5b3f6e31f222ef20b652c51..aaf55988b4c31fba967716d7f9d4dbb776d3593d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,20 +1,18 @@ -# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +# Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration # === Preamble === -cmake_minimum_required(VERSION 3.12...3.19.1) - -# Make the 'cmake' module directory visible to CMake. -list( APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake ) - -# Define color codes for CMake messages -include( cmake_colors_defs ) - +cmake_minimum_required(VERSION 3.16...3.26) # === Project's settings === -include( GeoModel-version ) +include( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/GeoModel-version.cmake ) project( "GeoModel" VERSION ${GeoModel_VERSION} LANGUAGES CXX ) +# Make the 'cmake' module directory visible to CMake. +list( APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake ) + # === Project wide setup === +# Define color codes for CMake messages +include( cmake_colors_defs ) # Use the GNU install directory names. include( GNUInstallDirs ) # Set a default build type @@ -22,26 +20,32 @@ include( BuildType ) # Set default build and C++ options include( configure_cpp_options ) -# === Externally provided content === - # By default prefer not to use frameworks on macOS. # But use it at a "LAST" resource, if no other options worked. # For details on the behaviour of this cache variable, see: # - https://cmake.org/cmake/help/v3.0/command/find_file.html if( APPLE ) -set( CMAKE_FIND_FRAMEWORK "LAST" CACHE STRING - "Framework finding behaviour on macOS" ) + set( CMAKE_FIND_FRAMEWORK "LAST" CACHE STRING "Framework finding behaviour on macOS" ) endif() -# Set up how the project handle some of its dependenices. Either by picking them +# === Externally provided content === +# Set up how the project handle some of its dependenices. Either by ing them # up from the environment, or building them itself. include( SetupEigen3 ) include( SetupXercesC ) include( SetupJSON ) -# Find the dependencies that the project always picks up from its environment. +# Find the dependencies that the project always s up from its environment. find_package( SQLite3 3.7.17 ) + +# === Enable testing functionality +# NOTE: this must be in the root CMakeLists.txt file +# even if the tests are defined in CMake files +# located in sub-directories. +enable_testing() + + # === Main targets built by this project === # switches to let users build specific packages on request @@ -53,10 +57,20 @@ option(GEOMODEL_BUILD_VISUALIZATION "Enable the build of GeoModelVisualization" option(GEOMODEL_BUILD_GEOMODELG4 "Enable the build of GeoModelG4" OFF) option(GEOMODEL_BUILD_FULLSIMLIGHT "Enable the build of FullSimLight" OFF) option(GEOMODEL_BUILD_FULLSIMLIGHT_PROFILING "Enable FullSimLight profiling targets" OFF) -#option(GEOMODEL_BUILD_LARCUSTOMSOLIDEXTENSION "Build the LArCustomSolidExtension" OFF) +option(GEOMODEL_BUILD_FSL "Enable the build of FSL and FullSimLight" OFF) option(GEOMODEL_BUILD_ATLASEXTENSIONS "Build the Custom ATLAS Extensions" OFF) +option(GEOMODEL_USE_QT6 "Use QT6 for Visualization and FSL" OFF) +if(GEOMODEL_BUILD_FSL AND GEOMODEL_BUILD_FULLSIMLIGHT) + message(STATUS "==> NOTE: You enabled both BUILD_FSL and BUILD_FULLSIMLIGHT. Since BUILD_FSL triggers the build of the FullSimLight package as well, I set BUILD_FULLSIMLIGHT to FALSE to avoid errors of 'double inclusion'") + set(GEOMODEL_BUILD_FULLSIMLIGHT FALSE) +endif() +if (GEOMODEL_USE_QT6) + set (QT_VERSION 6) +else() + set (QT_VERSION 5) +endif() if(GEOMODEL_BUILD_FULLSIMLIGHT_PROFILING) set(GEOMODEL_BUILD_FULLSIMLIGHT ON CACHE BOOL "Enable the build of FullSimLight" FORCE) @@ -71,11 +85,10 @@ list( APPEND BUILT_PACKAGES "GeoModelCore") add_subdirectory(GeoModelIO) list( APPEND BUILT_PACKAGES "GeoModelIO") - if(GEOMODEL_BUILD_ALL) - set(GEOMODEL_BUILD_TOOLS TRUE) - set(GEOMODEL_BUILD_VISUALIZATION TRUE) - set(GEOMODEL_BUILD_FULLSIMLIGHT TRUE) + set(GEOMODEL_BUILD_TOOLS TRUE) + set(GEOMODEL_BUILD_VISUALIZATION TRUE) + set(GEOMODEL_BUILD_FSL TRUE) endif() if(GEOMODEL_BUILD_TOOLS) @@ -96,16 +109,17 @@ endif() if(GEOMODEL_BUILD_FULLSIMLIGHT) set(GEOMODEL_BUILD_GEOMODELG4 TRUE) # FullSimLight needs GeoModelG4 add_subdirectory(FullSimLight) + list( APPEND BUILT_PACKAGES "FullSimLight") +endif() + +if(GEOMODEL_BUILD_FSL) + set(GEOMODEL_BUILD_GEOMODELG4 TRUE) # FullSimLight needs GeoModelG4 + add_subdirectory(FullSimLight)# FSL needs FullSimLight add_subdirectory(FSL) list( APPEND BUILT_PACKAGES "FullSimLight") list( APPEND BUILT_PACKAGES "FSL") endif() -#if(GEOMODEL_BUILD_LARCUSTOMSOLIDEXTENSION) -# add_subdirectory(LArCustomSolidExtension) -# list( APPEND BUILT_PACKAGES "LArCustomSolidExtension") -#endif() - if(GEOMODEL_BUILD_ATLASEXTENSIONS) if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/ATLASExtensions) if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/ATLASExtensions/CMakeLists.txt) @@ -119,38 +133,25 @@ if(GEOMODEL_BUILD_ATLASEXTENSIONS) endif() endif() - -if(GEOMODEL_BUILD_GEOMODELG4 OR GEOMODEL_BUILD_EXAMPLES_W_GEANT4) +if(GEOMODEL_BUILD_GEOMODELG4) add_subdirectory(GeoModelG4) + if(GEOMODEL_BUILD_EXAMPLES AND GEOMODEL_BUILD_EXAMPLES_W_GEANT4) + message(STATUS "==> NOTE: You enabled both GEOMODEL_BUILD_EXAMPLES and GEOMODEL_BUILD_EXAMPLES_W_GEANT4. Since GEOMODEL_BUILD_EXAMPLES triggers the build of the GEOMODEL_BUILD_EXAMPLES_W_GEANT4 as well, I set GEOMODEL_BUILD_EXAMPLES_W_GEANT4 to FALSE to avoid errors of 'double inclusion'") + set(GEOMODEL_BUILD_EXAMPLES_W_GEANT4 FALSE) + elseif (GEOMODEL_BUILD_EXAMPLES_W_GEANT4) + add_subdirectory(GeoModelExamples) + list( APPEND BUILT_PACKAGES "GeoModelExamples") + endif() list( APPEND BUILT_PACKAGES "GeoModelG4") endif() - # Print Build Info on screen include( PrintBuildInfo ) - -# A function to get a string with comma-separated package names from a list of packages -# NOTE: We could make use of list(JOIN ...) on CMake >= 3.12, -# but on Ubuntu 18 the apt package installs 3.10 instead -function(getCSVStringFromList inputList outputString) - #message("input: ${inputList}") # for debug - set(tempList "") - foreach( item ${inputList}) - list(APPEND tempList ${item}) - endforeach() - string (REPLACE ";" ", " outStr "${tempList}") - #message("string: ${outStr}") # for debug - set( ${outputString} ${outStr} PARENT_SCOPE) -endfunction() - - # Let the users know which and how many packages they are building list(LENGTH BUILT_PACKAGES BUILT_PACKAGES_LENGTH) -# -# list(JOIN BUILT_PACKAGES ", " BUILT_PACKAGES_STR) # list(JOIN) needs /CMake 3.12, which is missing on Ubuntu 18 by default -getCSVStringFromList( "${BUILT_PACKAGES}" BUILT_PACKAGES_STR ) -# +string(REPLACE ";" ", " BUILT_PACKAGES_STR "${BUILT_PACKAGES}") + message(STATUS "${BoldWhite}-----${ColourReset}") -message( STATUS "${BoldGreen}Building the following ${BUILT_PACKAGES_LENGTH} packages: ${BUILT_PACKAGES_STR}${ColourReset}") +message(STATUS "${BoldGreen}Building the following ${BUILT_PACKAGES_LENGTH} packages: ${BUILT_PACKAGES_STR}${ColourReset}") message(STATUS "${BoldWhite}-----${ColourReset}") diff --git a/FSL/CMakeLists.txt b/FSL/CMakeLists.txt index 8ab1479ffad02ad738d96d52e63f19a2245fd610..71e3a7131b3beff559728b327abc4cf44d08b387 100644 --- a/FSL/CMakeLists.txt +++ b/FSL/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.16...3.26) project(fsl VERSION 0.1 LANGUAGES CXX) @@ -10,6 +10,18 @@ if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) include( GeoModel-version ) # set the project, with the version taken from the GeoModel parent project project( "fsl" VERSION ${GeoModel_VERSION} LANGUAGES CXX ) + + #Choose QT version here: + option (GEOMODEL_USE_QT6 "Use Qt6 for Visualization" OFF) + + if (GEOMODEL_USE_QT6) + set (QT_VERSION 6) + else() + set (QT_VERSION 5) + endif() + + + # Define color codes for CMake messages include( cmake_colors_defs ) # Warn the users about what they are doing @@ -20,11 +32,7 @@ if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) "Framework finding behaviour on macOS" ) # Set up how the project handle some of its dependenices. Either by picking them # up from the environment, or building them itself. - if( NOT TARGET JSONExt ) - include( SetupJSON ) - endif() - # Set a flag to steer the of the subpackages - set( ${PROJECT_NAME}_INDIVIDUAL_BUILD ON ) + include( SetupJSON ) find_package (FullSimLight REQUIRED) add_definitions (-DFSLPLUGINROOT="${FullSimLight_DIR}/../../../${CMAKE_INSTALL_DATAROOTDIR}" ) message ( STATUS "FSL plugin files sought here: ${FullSimLight_DIR}/../../../${CMAKE_INSTALL_DATAROOTDIR}" ) @@ -62,9 +70,9 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) # Find the dependencies of the project. -find_package( Qt5 COMPONENTS Core Gui Widgets Sql PrintSupport OpenGL REQUIRED ) +find_package( Qt${QT_VERSION} COMPONENTS Core Gui Widgets Sql PrintSupport OpenGL REQUIRED ) -# Qt5 settings. +# Qt${QT_VERSION} settings. set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) @@ -80,18 +88,7 @@ set(PROJECT_SOURCES ${sources} ${headers} ${uis} ) add_executable(fsl ${PROJECT_SOURCES} ) - - -target_link_libraries(fsl PRIVATE Qt5::Widgets) - -if( GEOMODEL_USE_BUILTIN_JSON ) - add_dependencies(fsl JSONExt ) -endif() - -if( nlohmann_json_FOUND ) - target_link_libraries( fsl PRIVATE nlohmann_json::nlohmann_json ) -endif() - +target_link_libraries(fsl PRIVATE Qt${QT_VERSION}::Widgets nlohmann_json::nlohmann_json) # Install the executable. install( TARGETS fsl diff --git a/FSL/src/fsl_mainwindow.cpp b/FSL/src/fsl_mainwindow.cpp index 763d4c27baf006996d8163ccca49d21a6f792948..3db5f424fddbede727808f2e678246a6da813c0d 100644 --- a/FSL/src/fsl_mainwindow.cpp +++ b/FSL/src/fsl_mainwindow.cpp @@ -1160,6 +1160,11 @@ void FSLMainWindow::run_configuration() { QMessageBox::information(this, "Info", "First Select Geometry input"); return; } + if(magnetic_field_type == "Plugin" && (ui->lE_MAG_PLUG->text()).toStdString().empty()) + { + QMessageBox::information(this, "Info", "Please Specify Plugin Path for Magnetic Field"); + return; + } create_configuration(); std::string tmpConf = "/tmp/fslconfig-" + std::to_string(getuid()) + "-" + diff --git a/FullSimLight/CMakeLists.txt b/FullSimLight/CMakeLists.txt index 7742d0a7220d190cf1b59ef508490367e39c91a7..a758278193b8347318f37ee12ea53a5031aac161 100644 --- a/FullSimLight/CMakeLists.txt +++ b/FullSimLight/CMakeLists.txt @@ -1,307 +1,138 @@ # Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration # CMake settings -cmake_minimum_required( VERSION 3.14 ) - -# Dummy call to 'project()', needed to set 'PROJECT_SOURCE_DIR' -project( "FullSimLight" ) +cmake_minimum_required(VERSION 3.16...3.26) #Set up the project. Check if we build it with GeoModel or individually -if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) - # I am top-level project. - # Make the root module directory visible to CMake. - list( APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../cmake ) - # get global GeoModel version - include( GeoModel-version ) - # set the project, with the version taken from the GeoModel parent project - project( "FullSimLight" VERSION ${GeoModel_VERSION} LANGUAGES CXX ) - # Define color codes for CMake messages - include( cmake_colors_defs ) - # Warn the users about what they are doing - message(STATUS "${BoldGreen}Building ${PROJECT_NAME} individually, as a top-level project.${ColourReset}") - # Set a default build type - include( BuildType ) - # Set default build and C++ options - include( configure_cpp_options ) - set( CMAKE_FIND_FRAMEWORK "LAST" CACHE STRING - "Framework finding behaviour on macOS" ) - # Set up how the project handle some of its dependenices. Either by picking them - # up from the environment, or building them itself. - if( NOT TARGET JSONExt ) - include( SetupJSON ) - endif() - if( NOT TARGET XercesCBuiltIn ) - include( SetupXercesC ) - endif() - # Find the base GeoModel packages, which must be installed on the target system already - find_package( GeoModelCore REQUIRED ${GeoModel_VERSION} ) - find_package( GeoModelIO REQUIRED ${GeoModel_VERSION} ) - find_package( GeoModelG4 REQUIRED ${GeoModel_VERSION} ) - # Set a flag to steer the of the subpackages - set( ${PROJECT_NAME}_INDIVIDUAL_BUILD ON ) - # Print Build Info on screen - include( PrintBuildInfo ) +if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) + # I am top-level project. + # Make the root module directory visible to CMake. + list( APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../cmake ) + # get global GeoModel version + include( GeoModel-version ) + # set the project, with the version taken from the GeoModel parent project + project( FullSimLight VERSION ${GeoModel_VERSION} LANGUAGES CXX ) + # Define color codes for CMake messages + include( cmake_colors_defs ) + # Warn the users about what they are doing + message(STATUS "${BoldGreen}Building ${PROJECT_NAME} individually, as a top-level project.${ColourReset}") + # Set a default build type + include( BuildType ) + # Set default build and C++ options + include( configure_cpp_options ) + set( CMAKE_FIND_FRAMEWORK "LAST" CACHE STRING "Framework finding behaviour on macOS" ) + # Set up how the project handle some of its dependenices. Either by picking them + # up from the environment, or building them itself. + include( SetupJSON ) + include( SetupXercesC ) + # Find the base GeoModel packages, which must be installed on the target system already + find_package( GeoModelCore REQUIRED ${GeoModel_VERSION} ) + find_package( GeoModelIO REQUIRED ${GeoModel_VERSION} ) + find_package( GeoModelG4 REQUIRED ${GeoModel_VERSION} ) + # Print Build Info on screen + include( PrintBuildInfo ) else() - # I am called from other project with add_subdirectory(). - message( STATUS "Building ${PROJECT_NAME} as part of the root GeoModel project.") - # Set the project - project( "FullSimLight" VERSION ${GeoModel_VERSION} LANGUAGES CXX ) + # I am called from other project with add_subdirectory(). + message( STATUS "Building ${PROJECT_NAME} as part of the root GeoModel project.") + # Set the project + project( FullSimLight VERSION ${GeoModel_VERSION} LANGUAGES CXX ) endif() - ## External dependencies. #---------------------------------------------------------------------------- # Find Geant4 package, batch mode only executable (i.e. no need ui and vis). -# find_package(Geant4 REQUIRED) message( STATUS "Found Geant4: ${Geant4_INCLUDE_DIR}") -#---------------------------------------------------------------------------- - # Support for the HepMC3 exchange format # This is OFF by default, but it can be enbled by the user if used/needed; # for that, of course, HepMC3 must be installed on the system. option(GEOMODEL_USE_HEPMC3 "Build GeoModel tools with support for the HepMC3 exchancge format (Note: HepMC3 must be installed on the target machine)" OFF ) if(GEOMODEL_USE_HEPMC3) - find_package(HepMC3 REQUIRED) # if support for HEPMC3 is enabled, it must be installed. - if(HepMC3_FOUND) - message( STATUS "Found HepMC3 (${HEPMC3_INCLUDE_DIR}), and support for HepMC3 is enabled; so, support for it will be compiled.") - add_compile_definitions( USE_HEPMC3 ) - endif() -else() - message(STATUS "! NOTE ==> The support for HepMC3 is disabled by default, and it is not compiled at the moment. However, it can be enabled by the user by giving the option '-DGEOMODEL_USE_HEPMC3=1' to CMake; in that case, you must be sure HepMC3 is installed on the system.") -endif() -# If HepMC3 is not found, weather it is enabled or not by the user, -# we remove from the build the sources that use it -if( NOT HepMC3_FOUND) - file(GLOB hepmc3src ${PROJECT_SOURCE_DIR}/src/HepMC3*.cc) - #message("Removing those HepMC3-related sources: ${hepmc3src}") # debug msg - list(REMOVE_ITEM sources ${hepmc3src}) - #message("new sources without HepMC3 support: ${sources}") # debug msg + find_package(HepMC3 REQUIRED) # required by default, but it can be disabled endif() # Support for Pythia event generator # This is OFF by default, but it can be enbled by the user if used/needed; # for that, of course, Pythia must be installed on the system. - option(GEOMODEL_USE_PYTHIA "Build GeoModel tools with support for the Pythia event generator (Note: Pythia must be installed on the target machine)" OFF ) - if(GEOMODEL_USE_PYTHIA) - find_package(Pythia REQUIRED) # if support for Pythia is enabled, it must be installed. - if(Pythia_FOUND) - message( STATUS "Found Pythia (${Pythia_INCLUDE_DIR}), and support for Pythia is enabled; so, support for it will be compiled.") - add_compile_definitions( USE_PYTHIA ) - endif() -else() - message(STATUS "! NOTE ==> The support for Pythia is disabled by default, and it is not compiled at the moment. However, it can be enabled by the user by giving the option '-DGEOMODEL_USE_Pythia=1' to CMake; in that case, you must be sure Pythia is installed on the system.") + find_package(Pythia REQUIRED) # if support for Pythia is enabled, it must be installed. endif() - - - - - -#---------------------------------------------------------------------------- -# Setup Geant4 include directories and compile definitions -# Setup include directory for this project -# -#message("Geant4_USE_FILE: ${Geant4_USE_FILE}") # debug msg -include(${Geant4_USE_FILE}) -add_definitions (-DG4VERSION="${Geant4_VERSION}" ) - -# Find includes in corresponding build directories -set(CMAKE_INCLUDE_CURRENT_DIR ON) - - -# Add sub-projects and targets -add_subdirectory(Plugins) - - -# You need to tell CMake where to find the ROOT installation. This can be done in a number of ways: -# - ROOT built with classic configure/make use the provided $ROOTSYS/etc/cmake/FindROOT.cmake -# - ROOT built with CMake. Add in CMAKE_PREFIX_PATH the installation prefix for ROOT -#list(APPEND CMAKE_PREFIX_PATH $ENV{ROOTSYS}) - -#---Locate the ROOT package and defines a number of variables (e.g. ROOT_INCLUDE_DIRS) -#find_package(ROOT REQUIRED COMPONENTS RIO Net) - -#---Define useful ROOT functions and macros (e.g. ROOT_GENERATE_DICTIONARY) -#include(${ROOT_USE_FILE}) - - - -include_directories(${PROJECT_SOURCE_DIR}/include) - - #---------------------------------------------------------------------------- # Locate sources and headers for this project # file(GLOB sources ${PROJECT_SOURCE_DIR}/src/*.cc) -file(GLOB headers ${PROJECT_SOURCE_DIR}/inc/*.hh) -#message("sources: ${sources}") # debug msg +file(GLOB headers ${PROJECT_SOURCE_DIR}/include/*.hh) - -# Remove from the build HepMC3-related sources if that is not found -# TODO: remove these lines and put pre-comp fences with 'USE_HEPMC3' def -if( NOT HepMC3_FOUND) - file(GLOB hepmc3src ${PROJECT_SOURCE_DIR}/src/HepMC3*.cc) - #message("Removing those HepMC3-related sources: ${hepmc3src}") # debug msg - list(REMOVE_ITEM sources ${hepmc3src}) - #message("new sources without HepMC3 support: ${sources}") # debug msg +if(NOT HepMC3_FOUND) + file(GLOB hepmc3src ${PROJECT_SOURCE_DIR}/src/HepMC3*.cc) + list(REMOVE_ITEM sources ${hepmc3src}) endif() - #---------------------------------------------------------------------------- # Add the executable, and link it to the Geant4 libraries # set(OUTPUT bin) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${OUTPUT}) -add_definitions (-DG4SHAREDIR="${Geant4_INCLUDE_DIR}/../../share" ) -add_definitions (-DFULLSIMLIGHTSHAREDIR="${CMAKE_INSTALL_PREFIX}/share/FullSimLight" ) +# Plugin Interface Library +add_library(FullSimLight INTERFACE) +add_library(FullSimLight::FullSimLight ALIAS FullSimLight) +target_include_directories( FullSimLight INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>) + +# OBJECT library for the shared functionality +add_library(FullSimLight_obj OBJECT ${sources} ${headers}) +target_compile_definitions(FullSimLight_obj + PUBLIC + G4SHAREDIR="${Geant4_INCLUDE_DIR}/../../share" + FULLSIMLIGHTSHAREDIR="${CMAKE_INSTALL_PREFIX}/share/FullSimLight" + G4VERSION="${Geant4_VERSION}" + $<$<BOOL:${Pythia_FOUND}>:USE_PYTHIA> + $<$<BOOL:${HepMC3_FOUND}>:USE_HEPMC3>) +target_include_directories(FullSimLight_obj + PUBLIC + $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> + ${HEPMC3_INCLUDE_DIR}) +target_link_libraries(FullSimLight_obj + PUBLIC + nlohmann_json::nlohmann_json + GeoModel2G4 + GeoModelCore::GeoModelKernel + GeoModelCore::GeoModelFuncSnippets + GeoModelIO::GeoModelRead + GeoModelIO::GeoModelWrite + ${HEPMC3_LIB} + ${Geant4_LIBRARIES} + $<$<BOOL:${Pythia_FOUND}>:Pythia::Pythia> + PRIVATE + FullSimLight::FullSimLight) + +# Primary executables +add_executable(fullSimLight fullSimLight.cc) +target_link_libraries(fullSimLight PRIVATE FullSimLight_obj) + +add_executable(gmclash geoModelClash.cc) +target_link_libraries(gmclash PRIVATE FullSimLight_obj) + +add_executable(gmmasscalc geoModelMassCalculator.cc) +target_link_libraries(gmmasscalc PRIVATE FullSimLight_obj) + +add_executable(gmgeantino geantinoMaps.cc) +target_link_libraries(gmgeantino PRIVATE FullSimLight_obj) + +add_executable(gm2gdml geoModel2GDML.cc) +target_link_libraries(gm2gdml PRIVATE FullSimLight_obj) -add_executable(fullSimLight fullSimLight.cc ${sources} ${headers}) -add_executable(gmclash geoModelClash.cc ${sources} ${headers}) -add_executable(gmmasscalc geoModelMassCalculator.cc ${sources} ${headers}) add_executable(fillHistogramExample fillHistogramExample.cc src/Histo.cc include/Histo.hh) -add_executable(gmgeantino geantinoMaps.cc ${sources} ${headers}) -#add_executable(plotGeantinoMaps plotGeantinoMaps.cc) -#add_executable(testMagneticField testMagneticField.cc) -add_executable(gm2gdml geoModel2GDML.cc ${sources} ${headers}) - - - - -#if(HEPMC3_ROOTIO_USE) -# message( STATUS "HEPMC3 Root Dependency Switched on") -# target_link_libraries(gmclash PUBLIC ${HEPMC3_ROOTIO_LIB} ${ROOT_LIBRARIES}) - # target_link_libraries(gmmasscalc PUBLIC ${HEPMC3_ROOTIO_LIB} ${ROOT_LIBRARIES}) - # target_link_libraries(fullSimLight PUBLIC ${HEPMC3_ROOTIO_LIB} ${ROOT_LIBRARIES}) - # target_link_libraries(gmgeantino PUBLIC ${HEPMC3_ROOTIO_LIB} ${ROOT_LIBRARIES}) - # target_link_libraries(gm2gdml PUBLIC ${HEPMC3_ROOTIO_LIB} ${ROOT_LIBRARIES}) - # target_include_directories(gmclash PUBLIC ${ROOT_INCLUDE_DIRS}) - # target_include_directories(gmmasscalc PUBLIC ${ROOT_INCLUDE_DIRS}) - # target_include_directories(fullSimLight PUBLIC ${ROOT_INCLUDE_DIRS}) - # target_include_directories(gmgeantino PUBLIC ${ROOT_INCLUDE_DIRS}) - # target_include_directories(gm2gdml PUBLIC ${ROOT_INCLUDE_DIRS}) - - # target_compile_definitions(gmclash PRIVATE USE_ROOT) - #target_compile_definitions(gmmasscalc PRIVATE USE_ROOT) - # target_compile_definitions(fullSimLight PRIVATE USE_ROOT) - # target_compile_definitions(gmgeantino PRIVATE USE_ROOT) - # target_compile_definitions(gm2gdml PRIVATE USE_ROOT) -#endif() - -#---------------------------------------------------------------------------- -# Add extra 'include' directories -# -# If the in-house build of the nlohmann_json library is used, add explicit dependency -if( GEOMODEL_USE_BUILTIN_JSON ) - add_dependencies( fullSimLight JSONExt ) - add_dependencies( gmclash JSONExt ) - add_dependencies( gmmasscalc JSONExt ) - add_dependencies( fillHistogramExample JSONExt ) - add_dependencies( gmgeantino JSONExt ) - #add_dependencies( testMagneticField JSONExt ) - add_dependencies( gm2gdml JSONExt ) - # Acquire Installation Directory of JSONExt - ExternalProject_Get_Property (JSONExt install_dir) - # Include the installed 'include' PATH - include_directories (${install_dir}/include) -endif() -# If the in-house build of the Xerces-C library is used, add explicit dependency: for Geant4 -if( GEOMODEL_USE_BUILTIN_XERCESC ) - add_dependencies( fullSimLight XercesCBuiltIn ) - add_dependencies( gmclash XercesCBuiltIn ) - add_dependencies( gmmasscalc XercesCBuiltIn ) - add_dependencies( fillHistogramExample XercesCBuiltIn ) - add_dependencies( gmgeantino XercesCBuiltIn ) -# add_dependencies( testMagneticField XercesCBuiltIn ) - add_dependencies( gm2gdml XercesCBuiltIn ) -endif() -#---------------------------------------------------------------------------- -# Link all needed libraries -# +target_include_directories(fillHistogramExample PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include) target_link_libraries(fillHistogramExample ${Geant4_LIBRARIES}) -#target_link_libraries(testMagneticField ${Geant4_LIBRARIES} MagFieldInterfaces) -#target_link_libraries(plotGeantinoMaps ${ROOT_LIBRARIES}) - - -target_link_libraries(gmclash PUBLIC GeoModel2G4 ${Geant4_LIBRARIES} ) -target_link_libraries(gmmasscalc PUBLIC GeoModel2G4 ${Geant4_LIBRARIES} ) -target_link_libraries(fullSimLight PUBLIC GeoModel2G4 ${Geant4_LIBRARIES} ) -target_link_libraries(gmgeantino PUBLIC GeoModel2G4 ${Geant4_LIBRARIES} ) -target_link_libraries(gm2gdml PUBLIC GeoModel2G4 ${Geant4_LIBRARIES} ) - - -if( HepMC3_FOUND) - target_link_libraries(gmclash PUBLIC GeoModel2G4 ${HEPMC3_LIB}) - target_link_libraries(gmmasscalc PUBLIC GeoModel2G4 ${HEPMC3_LIB}) - target_link_libraries(fullSimLight PUBLIC GeoModel2G4 ${HEPMC3_LIB}) - target_link_libraries(gmgeantino PUBLIC GeoModel2G4 ${HEPMC3_LIB}) - target_link_libraries(gm2gdml PUBLIC GeoModel2G4 ${HEPMC3_LIB}) - target_include_directories(gmclash PUBLIC ${HEPMC3_INCLUDE_DIR}) - target_include_directories(gmmasscalc PUBLIC ${HEPMC3_INCLUDE_DIR}) - target_include_directories(fullSimLight PUBLIC ${HEPMC3_INCLUDE_DIR}) - target_include_directories(gmgeantino PUBLIC ${HEPMC3_INCLUDE_DIR}) - target_include_directories(gm2gdml PUBLIC ${HEPMC3_INCLUDE_DIR}) -endif() - -if(Pythia_FOUND) - target_compile_definitions(fullSimLight PRIVATE USE_PYTHIA) - target_compile_definitions(gmgeantino PRIVATE USE_PYTHIA) - target_compile_definitions(gmmasscalc PRIVATE USE_PYTHIA) - target_compile_definitions(gm2gdml PRIVATE USE_PYTHIA) - target_compile_definitions(gmclash PRIVATE USE_PYTHIA) - target_link_libraries(fullSimLight PUBLIC Pythia::Pythia) - target_link_libraries(gmgeantino PUBLIC Pythia::Pythia) - target_link_libraries(gmmasscalc PUBLIC Pythia::Pythia) - target_link_libraries(gm2gdml PUBLIC Pythia::Pythia) - target_link_libraries(gmclash PUBLIC Pythia::Pythia) - target_include_directories(fullSimLight PUBLIC ${Pythia_INCLUDE_DIR}) - target_include_directories(gmgeantino PUBLIC ${Pythia_INCLUDE_DIR}) - target_include_directories(gmmasscalc PUBLIC ${Pythia_INCLUDE_DIR}) - target_include_directories(gm2gdml PUBLIC ${Pythia_INCLUDE_DIR}) - target_include_directories(gmclash PUBLIC ${Pythia_INCLUDE_DIR}) -endif() - - -# Check if we are building FullSimLight individually, -# or as a part of the main GeoModel. -# In the first case, we link against the imported targets, which are taken -# from the base GeoModel packages already installed on the system. -# This is used when building distribution packages. -if ( ${PROJECT_NAME}_INDIVIDUAL_BUILD ) # if built individually - target_link_libraries( gmclash PUBLIC GeoModelCore::GeoModelKernel GeoModelIO::GeoModelRead GeoModelIO::GeoModelWrite ) - target_link_libraries( gmmasscalc PUBLIC GeoModelCore::GeoModelKernel GeoModelIO::GeoModelRead GeoModelIO::GeoModelWrite ) - target_link_libraries( fullSimLight PUBLIC GeoModelCore::GeoModelKernel GeoModelIO::GeoModelRead GeoModelIO::GeoModelWrite ) - target_link_libraries( gmgeantino PUBLIC GeoModelCore::GeoModelKernel GeoModelIO::GeoModelRead GeoModelIO::GeoModelWrite ) - target_link_libraries( gm2gdml PUBLIC GeoModelCore::GeoModelKernel GeoModelIO::GeoModelRead GeoModelIO::GeoModelWrite ) -else() # if built as a part of GeoModel - target_link_libraries( gmclash PUBLIC GeoModelKernel GeoModelRead GeoModelWrite ) - target_link_libraries( gmmasscalc PUBLIC GeoModelKernel GeoModelRead GeoModelWrite ) - target_link_libraries( fullSimLight PUBLIC GeoModelKernel GeoModelRead GeoModelWrite ) - target_link_libraries( gmgeantino PUBLIC GeoModelKernel GeoModelRead GeoModelWrite ) - target_link_libraries( gm2gdml PUBLIC GeoModelKernel GeoModelRead GeoModelWrite ) -endif() - -# targets that need 'nlohmann_json' -# NOTE: We link to `nlohmann_json` only if we use a version of nlohmann_json -# that provides a CMake config file (i.e., either built from source, or also -# installed with Homebrew on macOS). -# This is not needed if the single-header library is installed in a regular -# system include folder (e.g., '/usr/local/include', '/usr/include', ...) -if( nlohmann_json_FOUND ) - target_link_libraries( gmclash PRIVATE nlohmann_json::nlohmann_json ) - target_link_libraries( gmmasscalc PRIVATE nlohmann_json::nlohmann_json ) - target_link_libraries( fullSimLight PRIVATE nlohmann_json::nlohmann_json ) - target_link_libraries( gmgeantino PRIVATE nlohmann_json::nlohmann_json ) - target_link_libraries( gm2gdml PRIVATE nlohmann_json::nlohmann_json ) -else() - message(STATUS "WARNING - 'nlohmann_json' not found by CMake!! Anyway, if you installed the single header file in a standard system include dir, I will be able to use it.") -endif() #---------------------------------------------------------------------------- +# Add sub-projects and targets +add_subdirectory(Plugins) + # Add profiling test targets if(GEOMODEL_BUILD_FULLSIMLIGHT_PROFILING) if(NOT Pythia_FOUND) @@ -310,8 +141,6 @@ if(GEOMODEL_BUILD_FULLSIMLIGHT_PROFILING) add_subdirectory(perf) endif() -#ROOT_GENERATE_DICTIONARY(G__geantinoMaps ${headers} LINKDEF geantinoMapsLinkDef.h) - #---------------------------------------------------------------------------- # Copy all scripts to the build/OUTPUT directory. This is so that, after # install, we can run the executable directly because it relies on these @@ -339,72 +168,57 @@ foreach(_script ${FULLSIMLIGHT_SCRIPTS}) ) endforeach() - #---------------------------------------------------------------------------- -# Install the executable to 'bin/' directory under the +# Install the executables to 'bin/' directory under the # CMAKE_INSTALL_PREFIX # - - -install(TARGETS fullSimLight DESTINATION ${OUTPUT}) -install(TARGETS gmclash DESTINATION ${OUTPUT}) -install(TARGETS gmmasscalc DESTINATION ${OUTPUT}) -install(TARGETS fillHistogramExample DESTINATION ${OUTPUT}) -install(TARGETS gmgeantino DESTINATION ${OUTPUT}) -#install(TARGETS testMagneticField DESTINATION ${OUTPUT}) -install(TARGETS gm2gdml DESTINATION ${OUTPUT}) +install(TARGETS fullSimLight gmclash gmmasscalc fillHistogramExample gmgeantino gm2gdml + DESTINATION ${OUTPUT}) install(FILES ${FULLSIMLIGHT_SCRIPTS} DESTINATION share/FullSimLight) - - -add_library ( FullSimLight INTERFACE ) - # Set up the packaging of the project using CPack. -list( APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ) include ( GNUInstallDirs ) include( WriteBasicConfigVersionFile ) write_basic_config_version_file( - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${PROJECT_NAME}ConfigVersion.cmake - VERSION ${PROJECT_VERSION} - COMPATIBILITY SameMajorVersion ) + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${PROJECT_NAME}ConfigVersion.cmake + VERSION ${PROJECT_VERSION} + COMPATIBILITY SameMajorVersion ) install( - FILES - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${PROJECT_NAME}ConfigVersion.cmake - COMPONENT Development - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} ) + FILES + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${PROJECT_NAME}ConfigVersion.cmake + COMPONENT Development + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} ) #Create and install the description of the libraries. install( EXPORT ${PROJECT_NAME}-export - FILE ${PROJECT_NAME}Targets.cmake - COMPONENT Development -# NAMESPACE "${PROJECT_NAME}::" - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} ) + FILE ${PROJECT_NAME}Targets.cmake + COMPONENT Development + NAMESPACE "${PROJECT_NAME}::" + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} ) # Install the hand-written project configuration. configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/FullSimLightConfig.cmake.in - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${PROJECT_NAME}Config.cmake - @ONLY ) + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${PROJECT_NAME}Config.cmake + @ONLY ) install( - FILES - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${PROJECT_NAME}Config.cmake - COMPONENT Development - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} ) + FILES + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${PROJECT_NAME}Config.cmake + COMPONENT Development + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} ) install( TARGETS FullSimLight - EXPORT ${PROJECT_NAME}-export - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) + EXPORT ${PROJECT_NAME}-export + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) install(FILES FullSimLight/FSLSensitiveDetectorPlugin.h FullSimLight/MagFieldPlugin.h FullSimLight/FSLPhysicsListPlugin.h - FullSimLight/FSLUserActionPlugin.h - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/FullSimLight + FullSimLight/FSLUserActionPlugin.h + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/FullSimLight COMPONENT Development ) - - diff --git a/FullSimLight/Plugins/CMakeLists.txt b/FullSimLight/Plugins/CMakeLists.txt index 0e31deec640a8ca32761d23dc3649489a37f8d42..3fccb0bd3e167bd82d77bf22b9a1f7a5401eecfe 100644 --- a/FullSimLight/Plugins/CMakeLists.txt +++ b/FullSimLight/Plugins/CMakeLists.txt @@ -1,7 +1,7 @@ # Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration # CMake settings -cmake_minimum_required( VERSION 3.14 ) +cmake_minimum_required(VERSION 3.16...3.26) # Dummy call to 'project()', needed to set 'PROJECT_SOURCE_DIR' project( "Plugins" ) @@ -28,8 +28,6 @@ if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) # Find the base GeoModel packages, which must be installed on the target system already find_package( GeoModelCore REQUIRED ) - # Set a flag to steer the build of the subpackages - #set( VISUALIZATION_INDIVIDUAL_BUILD ON ) else() # I am called from other project with add_subdirectory(). message( STATUS "Building ${PROJECT_NAME} as part of the root GeoModel project.") diff --git a/FullSimLight/Plugins/Examples/EventGeneratorPlugins/FSLExamplePrimaryGeneratorPlugin/CMakeLists.txt b/FullSimLight/Plugins/Examples/EventGeneratorPlugins/FSLExamplePrimaryGeneratorPlugin/CMakeLists.txt index d7eb29db21b982d5c91d62bcacbcb81fc9493f77..9fd65c9ae2a7ffce3e50d0abb68b2e7a982c5539 100644 --- a/FullSimLight/Plugins/Examples/EventGeneratorPlugins/FSLExamplePrimaryGeneratorPlugin/CMakeLists.txt +++ b/FullSimLight/Plugins/Examples/EventGeneratorPlugins/FSLExamplePrimaryGeneratorPlugin/CMakeLists.txt @@ -1,5 +1,5 @@ # Set up the project. -cmake_minimum_required( VERSION 3.1 ) +cmake_minimum_required(VERSION 3.16...3.26) set(CMAKE_CXX_STANDARD 17) @@ -54,22 +54,11 @@ add_library(ExamplePrimaryGeneratorPlugin SHARED ${SOURCES}) find_package(Geant4 REQUIRED) message( STATUS "Found Geant4: ${Geant4_INCLUDE_DIR}") -#message("Geant4_USE_FILE: ${Geant4_USE_FILE}") # debug msg -include(${Geant4_USE_FILE}) # Use the GNU install directory names. include( GNUInstallDirs ) -# Add the FullSimLight headers dir. -# Path is different if built as a single top project, -# or as an all-in-one build together with all other GeoModel subpackages -if( FullSimLight_INDIVIDUAL_BUILD ) - target_include_directories( ExamplePrimaryGeneratorPlugin PUBLIC ${CMAKE_SOURCE_DIR} ) -else() # all-in-one--build - target_include_directories( ExamplePrimaryGeneratorPlugin PUBLIC ${CMAKE_SOURCE_DIR}/FullSimLight ) -endif() - -target_link_libraries ( ExamplePrimaryGeneratorPlugin PUBLIC ${CMAKE_DL_LIBS} ${Geant4_LIBRARIES}) +target_link_libraries ( ExamplePrimaryGeneratorPlugin PUBLIC FullSimLight::FullSimLight ${CMAKE_DL_LIBS} ${Geant4_LIBRARIES}) set_target_properties( ExamplePrimaryGeneratorPlugin PROPERTIES diff --git a/FullSimLight/Plugins/Examples/MagneticFieldPlugins/UniformMagneticFieldPlugin/CMakeLists.txt b/FullSimLight/Plugins/Examples/MagneticFieldPlugins/UniformMagneticFieldPlugin/CMakeLists.txt index dcd0dfeb7522733b94e3d6c087003aee07906543..d35108850b624744c98bdf01b1cf8b6d6149c808 100644 --- a/FullSimLight/Plugins/Examples/MagneticFieldPlugins/UniformMagneticFieldPlugin/CMakeLists.txt +++ b/FullSimLight/Plugins/Examples/MagneticFieldPlugins/UniformMagneticFieldPlugin/CMakeLists.txt @@ -1,5 +1,5 @@ # Set up the project. -cmake_minimum_required( VERSION 3.1 ) +cmake_minimum_required(VERSION 3.16...3.26) set(CMAKE_CXX_STANDARD 17) @@ -32,6 +32,7 @@ if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) set( CMAKE_FIND_FRAMEWORK "LAST" CACHE STRING "Framework finding behaviour on macOS" ) # GeoModel dependencies + find_package( FullSimLight REQUIRED ) find_package( GeoModelCore REQUIRED ) else() # I am called from other project with add_subdirectory(). @@ -53,26 +54,13 @@ add_library(UniformMagneticFieldPlugin SHARED ${SOURCES}) find_package(Geant4 REQUIRED) message( STATUS "Found Geant4: ${Geant4_INCLUDE_DIR}") -#message("Geant4_USE_FILE: ${Geant4_USE_FILE}") # debug msg -include(${Geant4_USE_FILE}) # Use the GNU install directory names. include( GNUInstallDirs ) add_definitions (-DMAPPATH="${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATAROOTDIR}" ) - -# Add the FullSimLight headers dir. -# Path is different if built as a single top project, -# or as an all-in-one build together with all other GeoModel subpackages -if( FullSimLight_INDIVIDUAL_BUILD ) - target_include_directories( UniformMagneticFieldPlugin PUBLIC ${CMAKE_SOURCE_DIR} ) -else() # all-in-one--build - target_include_directories( UniformMagneticFieldPlugin PUBLIC ${CMAKE_SOURCE_DIR}/FullSimLight ) -endif() - - -target_link_libraries ( UniformMagneticFieldPlugin PUBLIC ${CMAKE_DL_LIBS} ${Geant4_LIBRARIES} Eigen3::Eigen) +target_link_libraries ( UniformMagneticFieldPlugin PUBLIC FullSimLight::FullSimLight ${CMAKE_DL_LIBS} ${Geant4_LIBRARIES} Eigen3::Eigen) set_target_properties( UniformMagneticFieldPlugin PROPERTIES diff --git a/FullSimLight/Plugins/Examples/PhysicsListPlugins/FSLTestPhysListPlugins/CMakeLists.txt b/FullSimLight/Plugins/Examples/PhysicsListPlugins/FSLTestPhysListPlugins/CMakeLists.txt index c37cd349c3f808343119693b02e5efcfcaee0e86..26f3ffdccca3e7f9964baabba89876a07f76cefe 100644 --- a/FullSimLight/Plugins/Examples/PhysicsListPlugins/FSLTestPhysListPlugins/CMakeLists.txt +++ b/FullSimLight/Plugins/Examples/PhysicsListPlugins/FSLTestPhysListPlugins/CMakeLists.txt @@ -1,5 +1,5 @@ # Set up the project. -cmake_minimum_required( VERSION 3.1 ) +cmake_minimum_required(VERSION 3.16...3.26) set(CMAKE_CXX_STANDARD 17) @@ -31,6 +31,7 @@ if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) set( CMAKE_FIND_FRAMEWORK "LAST" CACHE STRING "Framework finding behaviour on macOS" ) # GeoModel dependencies + find_package( FullSimLight REQUIRED ) find_package( GeoModelCore REQUIRED ) else() # I am called from other project with add_subdirectory(). @@ -52,22 +53,11 @@ add_library(TestPhysicsListPlugin SHARED ${SOURCES}) find_package(Geant4 REQUIRED) message( STATUS "Found Geant4: ${Geant4_INCLUDE_DIR}") -#message("Geant4_USE_FILE: ${Geant4_USE_FILE}") # debug msg -include(${Geant4_USE_FILE}) # Use the GNU install directory names. include( GNUInstallDirs ) -# Add the FullSimLight headers dir. -# Path is different if built as a single top project, -# or as an all-in-one build together with all other GeoModel subpackages -if( FullSimLight_INDIVIDUAL_BUILD ) - target_include_directories( TestPhysicsListPlugin PUBLIC ${CMAKE_SOURCE_DIR} ) -else() # all-in-one--build - target_include_directories( TestPhysicsListPlugin PUBLIC ${CMAKE_SOURCE_DIR}/FullSimLight ) -endif() - -target_link_libraries ( TestPhysicsListPlugin PUBLIC ${CMAKE_DL_LIBS} ${Geant4_LIBRARIES}) +target_link_libraries ( TestPhysicsListPlugin PUBLIC FullSimLight::FullSimLight ${CMAKE_DL_LIBS} ${Geant4_LIBRARIES}) diff --git a/FullSimLight/Plugins/Examples/SensitiveDetectorPlugins/SDPlugin/CMakeLists.txt b/FullSimLight/Plugins/Examples/SensitiveDetectorPlugins/SDPlugin/CMakeLists.txt index 819b2d8fe056c8e81111b7b349b5daf0c653f33a..1456e99418125acc624b52baf32335cf619450e8 100644 --- a/FullSimLight/Plugins/Examples/SensitiveDetectorPlugins/SDPlugin/CMakeLists.txt +++ b/FullSimLight/Plugins/Examples/SensitiveDetectorPlugins/SDPlugin/CMakeLists.txt @@ -1,5 +1,5 @@ # Set up the project. -cmake_minimum_required( VERSION 3.1 ) +cmake_minimum_required(VERSION 3.16...3.26) set(CMAKE_CXX_STANDARD 17) @@ -32,6 +32,7 @@ if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) set( CMAKE_FIND_FRAMEWORK "LAST" CACHE STRING "Framework finding behaviour on macOS" ) # GeoModel dependencies + find_package( FullSimLight REQUIRED ) find_package( GeoModelCore REQUIRED ) else() # I am called from other project with add_subdirectory(). @@ -53,22 +54,12 @@ add_library(SDPlugin SHARED ${SOURCES}) find_package(Geant4 REQUIRED) message( STATUS "Found Geant4: ${Geant4_INCLUDE_DIR}") -#message("Geant4_USE_FILE: ${Geant4_USE_FILE}") # debug msg -include(${Geant4_USE_FILE}) # Use the GNU install directory names. include( GNUInstallDirs ) -# Add the FullSimLight headers dir. -# Path is different if built as a single top project, -# or as an all-in-one build together with all other GeoModel subpackages -if( FullSimLight_INDIVIDUAL_BUILD ) - target_include_directories( SDPlugin PUBLIC ${CMAKE_SOURCE_DIR} ) -else() # all-in-one--build - target_include_directories( SDPlugin PUBLIC ${CMAKE_SOURCE_DIR}/FullSimLight ) -endif() -target_link_libraries ( SDPlugin PUBLIC ${CMAKE_DL_LIBS} ${Geant4_LIBRARIES}) +target_link_libraries ( SDPlugin PUBLIC FullSimLight ${CMAKE_DL_LIBS} ${Geant4_LIBRARIES}) set_target_properties( SDPlugin PROPERTIES diff --git a/FullSimLight/Plugins/Examples/UserActionPlugins/CMakeLists.txt b/FullSimLight/Plugins/Examples/UserActionPlugins/CMakeLists.txt index 73e5e728720dd985711926ed1014c08f5b0264c4..436fd3c3cef3d4a494b4ddf260e67489fca34319 100644 --- a/FullSimLight/Plugins/Examples/UserActionPlugins/CMakeLists.txt +++ b/FullSimLight/Plugins/Examples/UserActionPlugins/CMakeLists.txt @@ -1,7 +1,7 @@ # (C) 2002-2022 CERN for the benefit of the ATLAS collaboration # Set up the project. -cmake_minimum_required( VERSION 3.1 ) +cmake_minimum_required(VERSION 3.16...3.26) project( "UserActionsPlugins" ) #Set up the project. Check if we build it with GeoModel or individually diff --git a/FullSimLight/Plugins/Examples/UserActionPlugins/DummyUserActionPlugin/CMakeLists.txt b/FullSimLight/Plugins/Examples/UserActionPlugins/DummyUserActionPlugin/CMakeLists.txt index 2cf5e92a851d3f3928b93e7d5c55abb788ff3363..01be23f979eb443398ebc624fcf3ed8e08b56d10 100644 --- a/FullSimLight/Plugins/Examples/UserActionPlugins/DummyUserActionPlugin/CMakeLists.txt +++ b/FullSimLight/Plugins/Examples/UserActionPlugins/DummyUserActionPlugin/CMakeLists.txt @@ -1,5 +1,5 @@ # Set up the project. -cmake_minimum_required( VERSION 3.1 ) +cmake_minimum_required(VERSION 3.16...3.26) set(CMAKE_CXX_STANDARD 17) @@ -31,6 +31,7 @@ if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) set( CMAKE_FIND_FRAMEWORK "LAST" CACHE STRING "Framework finding behaviour on macOS" ) # GeoModel dependencies + find_package( FullSimLight REQUIRED ) find_package( GeoModelCore REQUIRED ) else() # I am called from other project with add_subdirectory(). @@ -49,28 +50,15 @@ set(PROJECT_SOURCES ${SOURCES}) # Set up the library. add_library(DummyUserActionPlugin SHARED ${SOURCES}) -#find_package (Eigen3 REQUIRED) find_package(Geant4 REQUIRED) -#find_package(FullSimLight REQUIRED) find_package( HDF5 REQUIRED COMPONENTS CXX ) message( STATUS "Found Geant4: ${Geant4_INCLUDE_DIR}") -#message("Geant4_USE_FILE: ${Geant4_USE_FILE}") # debug msg -include(${Geant4_USE_FILE}) # Use the GNU install directory names. include( GNUInstallDirs ) -# Add the FullSimLight headers dir. -# Path is different if built as a single top project, -# or as an all-in-one build together with all other GeoModel subpackages -if( FullSimLight_INDIVIDUAL_BUILD ) - target_include_directories( DummyUserActionPlugin PUBLIC ${CMAKE_SOURCE_DIR} ${HDF5_CXX_INCLUDE_DIRS}) -else() # all-in-one--build - target_include_directories( DummyUserActionPlugin PUBLIC ${CMAKE_SOURCE_DIR}/FullSimLight ${HDF5_CXX_INCLUDE_DIRS}) -endif() - -target_link_libraries ( DummyUserActionPlugin PUBLIC ${CMAKE_DL_LIBS} ${Geant4_LIBRARIES} ${HDF5_CXX_LIBRARIES}) +target_link_libraries ( DummyUserActionPlugin PUBLIC FullSimLight::FullSimLight ${CMAKE_DL_LIBS} ${Geant4_LIBRARIES} ${HDF5_CXX_LIBRARIES}) diff --git a/FullSimLight/Plugins/Examples/UserActionPlugins/DummyUserActionPlugin/DummyUserActionsPlugin/CMakeLists.txt b/FullSimLight/Plugins/Examples/UserActionPlugins/DummyUserActionPlugin/DummyUserActionsPlugin/CMakeLists.txt index 71a9be12c1fa7ae527295946de068d5687e6b171..617b3e584f677bbb1b40118bd207ff18a39decd0 100644 --- a/FullSimLight/Plugins/Examples/UserActionPlugins/DummyUserActionPlugin/DummyUserActionsPlugin/CMakeLists.txt +++ b/FullSimLight/Plugins/Examples/UserActionPlugins/DummyUserActionPlugin/DummyUserActionsPlugin/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration # Set up the project. -cmake_minimum_required( VERSION 3.1 ) +cmake_minimum_required(VERSION 3.16...3.26) project( "DummyUserActionsPlugin" ) @@ -23,9 +23,7 @@ if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) "Framework finding behaviour on macOS" ) # Set up how the project handle some of its dependenices. Either by picking them # up from the environment, or building them itself. - if( NOT TARGET XercesCBuiltIn ) - include( SetupXercesC ) - endif() + include( SetupXercesC ) # Find the base GeoModelATLAS packages, which must be installed on the target system already find_package( GeoModelDataManagers REQUIRED ${GeoModelATLAS_VERSION} ) else() diff --git a/FullSimLight/Plugins/HitsPlugin/CMakeLists.txt b/FullSimLight/Plugins/HitsPlugin/CMakeLists.txt index e9fb430c20446ee783972c63c06bf8525ef17699..f6e623af9b1ae51335333fb04687585c94112fa2 100644 --- a/FullSimLight/Plugins/HitsPlugin/CMakeLists.txt +++ b/FullSimLight/Plugins/HitsPlugin/CMakeLists.txt @@ -1,5 +1,5 @@ # Set up the project. -cmake_minimum_required( VERSION 3.1 ) +cmake_minimum_required(VERSION 3.16...3.26) set(CMAKE_CXX_STANDARD 17) @@ -51,31 +51,17 @@ set(PROJECT_SOURCES ${SOURCES}) # Set up the library. add_library(GenerateHitsPlugin SHARED ${SOURCES}) -#find_package (Eigen3 REQUIRED) find_package(Geant4 REQUIRED) -#find_package(FullSimLight REQUIRED) find_package( HDF5 REQUIRED COMPONENTS CXX ) message( STATUS "Found Geant4: ${Geant4_INCLUDE_DIR}") -#message("Geant4_USE_FILE: ${Geant4_USE_FILE}") # debug msg -include(${Geant4_USE_FILE}) # Use the GNU install directory names. include( GNUInstallDirs ) -# Add the FullSimLight headers dir. -# Path is different if built as a single top project, -# or as an all-in-one build together with all other GeoModel subpackages -if( FullSimLight_INDIVIDUAL_BUILD ) - target_include_directories( GenerateHitsPlugin PUBLIC ${CMAKE_SOURCE_DIR} ${HDF5_CXX_INCLUDE_DIRS}) -else() # all-in-one--build - target_include_directories( GenerateHitsPlugin PUBLIC ${CMAKE_SOURCE_DIR}/FullSimLight ${HDF5_CXX_INCLUDE_DIRS}) -endif() - -target_link_libraries ( GenerateHitsPlugin PUBLIC ${CMAKE_DL_LIBS} ${Geant4_LIBRARIES} ${HDF5_CXX_LIBRARIES}) - - +target_include_directories( GenerateHitsPlugin PUBLIC ${HDF5_CXX_INCLUDE_DIRS}) +target_link_libraries ( GenerateHitsPlugin PUBLIC FullSimLight::FullSimLight ${CMAKE_DL_LIBS} ${Geant4_LIBRARIES} ${HDF5_CXX_LIBRARIES}) set_target_properties( GenerateHitsPlugin PROPERTIES VERSION ${PROJECT_VERSION} diff --git a/FullSimLight/Plugins/TracksPlugin/CMakeLists.txt b/FullSimLight/Plugins/TracksPlugin/CMakeLists.txt index 21a411fbe9c6da14103555d6952596599c8c86ce..8797d01ad88f8dddc3301440c5242d4f25b8c24d 100644 --- a/FullSimLight/Plugins/TracksPlugin/CMakeLists.txt +++ b/FullSimLight/Plugins/TracksPlugin/CMakeLists.txt @@ -1,5 +1,5 @@ # Set up the project. -cmake_minimum_required( VERSION 3.1 ) +cmake_minimum_required(VERSION 3.16...3.26) set(CMAKE_CXX_STANDARD 17) @@ -32,6 +32,7 @@ if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) "Framework finding behaviour on macOS" ) # GeoModel dependencies find_package( GeoModelCore REQUIRED ) + find_package( FullSimLight REQUIRED ) else() # I am called from other project with add_subdirectory(). message( STATUS "Building ${PROJECT_NAME} as part of the root project.") @@ -50,28 +51,18 @@ set(PROJECT_SOURCES ${HEADERS} ${SOURCES} TracksPlugin.cc) # Set up the library. add_library(GenerateTracksPlugin SHARED ${HEADERS} ${SOURCES} TracksPlugin.cc) -#find_package (Eigen3 REQUIRED) find_package(Geant4 REQUIRED) -#find_package(FullSimLight REQUIRED) find_package( HDF5 REQUIRED COMPONENTS CXX ) message( STATUS "Found Geant4: ${Geant4_INCLUDE_DIR}") -#message("Geant4_USE_FILE: ${Geant4_USE_FILE}") # debug msg -include(${Geant4_USE_FILE}) # Use the GNU install directory names. include( GNUInstallDirs ) # Add the FullSimLight headers dir. -# Path is different if built as a single top project, -# or as an all-in-one build together with all other GeoModel subpackages -if( FullSimLight_INDIVIDUAL_BUILD ) - target_include_directories( GenerateTracksPlugin PUBLIC ${CMAKE_SOURCE_DIR} ${HDF5_CXX_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/include) -else() # all-in-one--build - target_include_directories( GenerateTracksPlugin PUBLIC ${CMAKE_SOURCE_DIR}/FullSimLight ${HDF5_CXX_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/include) -endif() +target_include_directories( GenerateTracksPlugin PUBLIC ${HDF5_CXX_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/include) -target_link_libraries ( GenerateTracksPlugin PUBLIC ${CMAKE_DL_LIBS} ${Geant4_LIBRARIES} ${HDF5_CXX_LIBRARIES}) +target_link_libraries ( GenerateTracksPlugin PUBLIC FullSimLight::FullSimLight ${CMAKE_DL_LIBS} ${Geant4_LIBRARIES} ${HDF5_CXX_LIBRARIES}) set_target_properties( GenerateTracksPlugin PROPERTIES VERSION ${PROJECT_VERSION} diff --git a/FullSimLight/fullSimLight.cc b/FullSimLight/fullSimLight.cc index e5210d9fbbe976fbf15853b5d023ca83b8106b6a..c61e9bd36bf57d7c5b5dc1ce1f165422eefd9ad8 100644 --- a/FullSimLight/fullSimLight.cc +++ b/FullSimLight/fullSimLight.cc @@ -35,8 +35,6 @@ #include <nlohmann/json.hpp> #include <fstream> -#include "HistoMessenger.hh" -#include "HistoManager.hh" #include "G4StepLimiterPhysics.hh" static const std::string fullSimLightShareDir=FULLSIMLIGHTSHAREDIR; diff --git a/FullSimLight/geantino_HGTD.g4 b/FullSimLight/geantino_HGTD.g4 new file mode 100644 index 0000000000000000000000000000000000000000..45f163a7e9629029a234d7148b226276ef6b9c68 --- /dev/null +++ b/FullSimLight/geantino_HGTD.g4 @@ -0,0 +1,50 @@ +######################################################################## +## SET ALL VERBOSE LEVELS TO 0 +## --------------------------------------------------------------------- +/control/verbose 0 +/run/verbose 0 +/event/verbose 0 +/tracking/verbose 0 +######################################################################## +## SET NUMBER OF THREADS (will be ignored in case of sequential Geant4) +## --------------------------------------------------------------------- +/run/numberOfThreads 1 +/control/cout/prefixString G4Worker_ +######################################################################## +## MAGNETIC FIELD +## --------------------------------------------------------------------- +/FSLdet/setField 0 tesla +######################################################################## +## Geantino Maps Configuration +## --------------------------------------------------------------------- +/gmaps/rmin 110 mm +/gmaps/rmax 1000 mm +/gmaps/zmin 3420 mm +/gmaps/zmax 3545 mm +/gmaps/xmin 110 mm +/gmaps/xmax 1000 mm +/gmaps/ymin 110 mm +/gmaps/ymax 1000 mm +/gmaps/etamin -6 +/gmaps/etamax 6 +/gmaps/volumeslist HGTD +######################################################################## +## INIT +## --------------------------------------------------------------------- +/run/initialize +######################################################################## +## PRIMARY GENERATOR +## --------------------------------------------------------------------- +/gps/verbose 0 +/gps/particle geantino +#/gps/pos/type Plane +#/gps/pos/shape Square +#/gps/pos/centre 1 2 1 cm +#/gps/pos/halfx 2 cm +#/gps/pos/halfy 2 cm +/gps/ang/type iso +/gps/energy 10 GeV +######################################################################## +## EXECUTE with 100000 events +## --------------------------------------------------------------------- +/run/beamOn 100000 diff --git a/FullSimLight/geoModel2GDML.cc b/FullSimLight/geoModel2GDML.cc index 0542ec842e7f6a94ba09ae25f0a646c5f0a933f2..9b4f5f0990e9171fc49b2093ae0ae821c6d11490 100644 --- a/FullSimLight/geoModel2GDML.cc +++ b/FullSimLight/geoModel2GDML.cc @@ -1,34 +1,39 @@ - //-------------------------------------------------------- // gm2gdml application: 8th June 2020 (README) //-------------------------------------------------------- #include "G4Version.hh" -#include "Randomize.hh" #include "FSLDetectorConstruction.hh" +#include "G4Timer.hh" + +#include "G4DisplacedSolid.hh" +#include "G4LogicalVolumeStore.hh" +#include "G4PhysicalVolumeStore.hh" #include <getopt.h> #include <err.h> #include <iostream> #include <iomanip> -static G4String inputGeometryFileName ; -static G4String outputGDMLFileName = "geometry.gdml"; +G4String inputGeometryFileName; +G4String outputGDMLFileName = "geometry.gdml"; +std::vector<G4VPhysicalVolume*> modified_volumes; void GetInputArguments(int argc, char** argv); void Help(); +void EliminateDisplacedSolids(); int main(int argc, char** argv) { - + // Get input arguments GetInputArguments(argc, argv); - + G4cout << " =================== Running GeoModel2GDML =================== " << G4endl << " Input geometry file name = " << inputGeometryFileName << G4endl << " Output GDML geometry file name = " << outputGDMLFileName << G4endl << " ============================================================== " << G4endl; - + // version banner G4String vs = G4Version; vs = vs.substr(1,vs.size()-2); @@ -46,31 +51,56 @@ int main(int argc, char** argv) { << " WWW : http://geant4.org/" << G4endl << "**************************************************************" << G4endl << G4endl; - - - // choose the Random engine: set to MixMax explicitely - // (default from 10.4) - G4Random::setTheEngine(new CLHEP::MixMaxRng); - // set seed and print info - G4Random::setTheSeed(12345678); - - G4cout << G4endl - << " Random engine = " << G4Random::getTheEngine()->name() << G4endl - << " Initial seed = " << G4Random::getTheSeed() << G4endl - << G4endl; - + // Detector construction FSLDetectorConstruction* detector = new FSLDetectorConstruction; - detector->SetDumpGDML(true); - detector->SetGeometryFileName (inputGeometryFileName); - detector->SetOutputGDMLFileName (outputGDMLFileName); - detector->Construct(); - + detector->SetGeometryFileName(inputGeometryFileName); + G4VPhysicalVolume* world = detector->Construct(); + + // Dump geometry + G4Timer timer; + timer.Start(); + G4cout << "\n =================== Dump geometry in GDML format =================== \n" << G4endl; + + // Remove volumes with custom shapes + detector->PullUnidentifiedVolumes(world->GetLogicalVolume()); + + // Eliminate G4DisplacedSolids, if any + std::vector<G4LogicalVolume*>* lv_store = G4LogicalVolumeStore::GetInstance(); + for (int i = 0; i < int(lv_store->size()); ++i) + { + G4LogicalVolume* logical = lv_store->at(i); + G4VSolid* solid = logical->GetSolid(); + if (solid->GetEntityType() != "G4DisplacedSolid") continue; + G4cout << " !ELIMINATING G4DisplacedSolid objects, shape is not supported in GDML! \n" << G4endl; + EliminateDisplacedSolids(); + break; + } + G4GDMLParser parser; + parser.Write(outputGDMLFileName, world->GetLogicalVolume()); + + timer.Stop(); + G4cout << G4endl; + G4cout << "**** Real time elapsed : " << timer.GetRealElapsed() << G4endl; + G4cout << "**** User time elapsed : " << timer.GetUserElapsed() << G4endl; + G4cout << "**** System time elapsed : " << timer.GetSystemElapsed() << G4endl; + G4cout << "\n =================== Geometry exported in GDML, DONE! =================== \n" << G4endl; + + // Free allocated memory + for (int i = 0; i < int(modified_volumes.size()); ++i) + { + G4VPhysicalVolume* v = modified_volumes[i]; + G4RotationMatrix* r = v->GetRotation(); + if (r == nullptr) continue; + delete r; + v->SetRotation(nullptr); + } + delete detector; return 0; } -static struct option options[] = { +struct option options[] = { {"input geometry file name " , required_argument, 0, 'g'}, {"output geometry gdml file name " , required_argument, 0, 'o'}, {"help" , no_argument , 0, 'h'}, @@ -100,7 +130,7 @@ void GetInputArguments(int argc, char** argv) { { Help(); exit(0); - + } while (true) { int c, optidx = 0; @@ -131,13 +161,84 @@ void GetInputArguments(int argc, char** argv) { G4cout << "\n *** ERROR : Input geometry file is required! " << G4endl; Help(); exit(-1); - + } // check that the output file as .gdml extention if (!outputGDMLFileName.contains(".gdml")) { G4cout << "\n *** ERROR : Output geometry file must have .gdml extension! " << G4endl; Help(); exit(-1); - + + } +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Auxiliary function for EliminateDisplacedSolids() + +void SetTransformation(G4VPhysicalVolume* v, G4Transform3D& t) +{ + G4RotationMatrix* old_rotation = v->GetRotation(); + G4RotationMatrix new_rotation = t.getRotation().inverse(); + if (old_rotation != nullptr) { + *old_rotation = new_rotation; + } else { + if (!new_rotation.isIdentity()) { + G4RotationMatrix* r = new G4RotationMatrix(new_rotation); + v->SetRotation(r); + modified_volumes.push_back(v); + } + } + v->SetTranslation(t.getTranslation()); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Replace displaced solids in volumes + +void EliminateDisplacedSolids() { + std::vector<G4LogicalVolume*> lv_vector; + std::vector<G4VPhysicalVolume*>* pv_store = G4PhysicalVolumeStore::GetInstance(); + + // Find logical volumes constructed from displaced solids and + // modify transformation in corresponding physical volumes + for (int i = 0; i < int(pv_store->size()); ++i) + { + G4VPhysicalVolume* physical = pv_store->at(i); + G4LogicalVolume* logical = physical->GetLogicalVolume(); + G4VSolid* solid = logical->GetSolid(); + if (solid->GetEntityType() != "G4DisplacedSolid") continue; + // select logical volume + lv_vector.push_back(logical); + // modify transformation in physical volume + G4DisplacedSolid* displaced = (G4DisplacedSolid*)solid; + G4Transform3D t1(displaced->GetObjectRotation(), displaced->GetObjectTranslation()); + G4Transform3D t2(physical->GetObjectRotationValue(), physical->GetObjectTranslation()); + G4Transform3D tt = t2*t1; + SetTransformation(physical, tt); + } + + // Replace solid in selected logical volumes and + // modify transformation in daughter physical volumes + int nlv = lv_vector.size(); + for (int i = 0; i < nlv; ++i) + { + G4LogicalVolume* logical = lv_vector[i]; + G4VSolid* solid = logical->GetSolid(); + if (solid->GetEntityType() != "G4DisplacedSolid") continue; + // replace solid + G4DisplacedSolid* displaced = (G4DisplacedSolid*)solid; + logical->SetSolid(displaced->GetConstituentMovedSolid()); + // modify transformation in daughter physical volumes + G4Transform3D t1(displaced->GetObjectRotation(), displaced->GetObjectTranslation()); + t1 = t1.inverse(); + int nd = logical->GetNoDaughters(); + for (int k = 0; k < nd; ++k) + { + G4VPhysicalVolume* daughter = logical->GetDaughter(k); + G4Transform3D t2(daughter->GetObjectRotationValue(), daughter->GetObjectTranslation()); + G4Transform3D tt = t1*t2; + SetTransformation(daughter, tt); } + } } diff --git a/FullSimLight/include/ATLFieldManager.hh b/FullSimLight/include/ATLFieldManager.hh index 1e3a3fcb6c4f152836268675ae1f9d392f27e2ed..4b500c3485ddb4298f4c42eab47a710329e36215 100644 --- a/FullSimLight/include/ATLFieldManager.hh +++ b/FullSimLight/include/ATLFieldManager.hh @@ -4,8 +4,7 @@ #define ATLFieldManager_h 1 #include "G4FieldManager.hh" -#include "FSLDetectorConstruction.hh" -#include "FSLDetectorMessenger.hh" + #include <string> #include <unordered_map> #include <memory> // Add this include for std::unique_ptr @@ -75,6 +74,7 @@ private: std::unordered_map<std::string, double> parameters; }; + template <typename T> T ParameterSet::getParameter(const std::string& key) const { auto it = parameters.find(key); @@ -131,6 +131,12 @@ private: void setDefaultChordFinder(); void setChordFinderForTracker(); void setChordFinderForBeampipe(); +<<<<<<< HEAD +======= + void ConfigureForTrack(const G4Track*) ; + + void printParameters(const std::string& region); +>>>>>>> 6b405a9246dbe177ebe3381b65003bcd666d7d18 void printParameters(const std::string& regionName); void printParametersForBeampipe(const std::string& regionName); diff --git a/FullSimLight/include/FSLDetectorConstruction.hh b/FullSimLight/include/FSLDetectorConstruction.hh index b5567531c8779a33dce85f633d75cdc731f920aa..1b7cc42609790d6ef6c5882cf2e6d1cb1d98f8a9 100644 --- a/FullSimLight/include/FSLDetectorConstruction.hh +++ b/FullSimLight/include/FSLDetectorConstruction.hh @@ -1,7 +1,10 @@ - +/* + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration +*/ #ifndef FSLDetectorConstruction_h #define FSLDetectorConstruction_h 1 +#include "GeoModelKernel/GeoVPhysVol.h" #include "G4VUserDetectorConstruction.hh" #include "G4GDMLParser.hh" @@ -51,8 +54,6 @@ #include "G4StepLimiter.hh" //#include "StepMax.hh" #include <cassert> -#include "HistoManager.hh" -#include "HistoMessenger.hh" #include "G4Track.hh" #include "G4SteppingManager.hh" #include "ATLFieldManager.hh" @@ -143,7 +144,6 @@ public: static G4double GetFieldValue() { return gFieldValue; } G4double GetTolerance (){return fTolerance;} - GeoPhysVol* CreateTheWorld(GeoPhysVol* world); /// Clean the geometry from Unidentified volumes before dumping it in GDML format void PullUnidentifiedVolumes( G4LogicalVolume* v ); diff --git a/FullSimLight/include/MassCalculator.hh b/FullSimLight/include/MassCalculator.hh index 249c84b9f654b83ddef745195208a4b45500ff77..1fd969f3126d7ec08e08e9234997d88179f8bf8e 100644 --- a/FullSimLight/include/MassCalculator.hh +++ b/FullSimLight/include/MassCalculator.hh @@ -1,3 +1,7 @@ +/* + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration +*/ + #ifndef MassCalculator_h #define MassCalculator_h 1 @@ -44,7 +48,7 @@ public: double inclusiveMass(const PVConstLink& pv); void calculateMass(G4LogicalVolume* logVol, G4VPhysicalVolume * physVol, std::vector<json>& jlist, double& exclusiveMass, bool writeRep); void iterateFromWorldMass(G4LogicalVolume* logVolume, std::vector<json>& jlist, double& inclusiveMass, double& exclusiveMass, G4String prefix, G4String material); - void recursiveMassCalculation (G4VPhysicalVolume* worldg4, GeoPhysVol* /*worldgeoModel*/, std::vector<json>& jlist); + void recursiveMassCalculation (G4VPhysicalVolume* worldg4, const GeoVPhysVol* /*worldgeoModel*/, std::vector<json>& jlist); void SetPrefixLogicalVolume(const G4String &prefixLV) { fPrefixLogicalVolume = prefixLV; } void SetMaterial(const G4String &material) { fMaterial = material; } void SetVerbosity(const int verbosity){ fVerbosityFlag = verbosity; } diff --git a/FullSimLight/perf/CMakeLists.txt b/FullSimLight/perf/CMakeLists.txt index 8215406042ca7dff20db39da14b08e7b9355e508..c4d585389b6246200fa82b0e39ded126d72604d0 100644 --- a/FullSimLight/perf/CMakeLists.txt +++ b/FullSimLight/perf/CMakeLists.txt @@ -1,5 +1,4 @@ -cmake_minimum_required(VERSION 3.12 FATAL_ERROR) -cmake_policy(VERSION 3.12...3.18) +cmake_minimum_required(VERSION 3.16...3.26) project(FullSimLightPerf) diff --git a/FullSimLight/src/ATLFieldManager.cc b/FullSimLight/src/ATLFieldManager.cc index c8f2d1b9527da430b87e395542caca71b0d912d4..38e5ce5d4242f80622bf170a1f1565f95b950610 100644 --- a/FullSimLight/src/ATLFieldManager.cc +++ b/FullSimLight/src/ATLFieldManager.cc @@ -112,7 +112,11 @@ #include "G4StepLimiter.hh" //#include "StepMax.hh" #include <cassert> +<<<<<<< HEAD #include "HistoManager.hh" +======= + +>>>>>>> 6b405a9246dbe177ebe3381b65003bcd666d7d18 #include "G4RegionStore.hh" #include "G4Region.hh" #include "G4Track.hh" @@ -123,7 +127,7 @@ #include "G4Step.hh" #include "G4ThreeVector.hh" //////// -#include "CLHEP/Units/GlobalSystemOfUnits.h" + #include "G4ChordFinder.hh" #include "G4MagIntegratorStepper.hh" #include "G4PropagatorInField.hh" @@ -146,14 +150,20 @@ ATLFieldManager::ATLFieldManager() m_stepMaxDefault(1000.), ////limit m_dChordTracker(0.0001), //Tracker m_dIntersectionTracker(0.0004), - m_dOneStepTracker(0.001), + m_dOneStepTracker(0.001), m_stepMaxTracker(100.), m_Rmax2(1.e+6), //10 meter m_Zmax(3.e+3), //0.3 meter +<<<<<<< HEAD m_energyThTracker(0.0), //0.2 GeV m_energyThreshold(0.0), // EnergyThSimple = cms.double(0.015), ## in GeV +======= + + m_energyThTracker(0.0), + m_energyThreshold(0.0), +>>>>>>> 6b405a9246dbe177ebe3381b65003bcd666d7d18 m_dChordBeampipe(0.002), //Beampipe m_dIntersectionBeampipe(0.003), @@ -161,7 +171,11 @@ ATLFieldManager::ATLFieldManager() m_stepMaxBeampipe(1000.0), m_cfTracker(false), +<<<<<<< HEAD m_cfBeampipe(false) {} +======= + m_cfBeampipe(false) { +>>>>>>> 6b405a9246dbe177ebe3381b65003bcd666d7d18 ATLFieldManager::~ATLFieldManager() = default; // ATLFieldManager::~ATLFieldManager() { @@ -233,10 +247,14 @@ void ATLFieldManager::InitialiseForVolume(const ParameterSet ¶ms, double rmax = params.getDoubleParameter("Rmax") * CLHEP::mm; m_Rmax2 = rmax * rmax; +<<<<<<< HEAD m_Zmax = params.getDoubleParameter("Zmax") * CLHEP::mm; //overwrite m_Rmax2= 8000 * CLHEP::mm; //10 meter m_Zmax = 12000 * CLHEP::mm; +======= + m_Zmax = params.getDoubleParameter("Zmax") * CLHEP::mm; +>>>>>>> 6b405a9246dbe177ebe3381b65003bcd666d7d18 std::cout << "is it workinggggggggg!" ">\n" //edm::LogVerbatim("") @@ -331,7 +349,39 @@ std::cout << "ccccccc" << ">\n"; } std::cout << "is it workinggggggggg!" << std::endl; } +<<<<<<< HEAD + +======= + + /* +>>>>>>> dedbbe927cafde8861ebe5968921156c3093037c + void ATLFieldManager::ConfigureForTrack(const G4Track *track) { + // run time parameters per track + if (track->GetKineticEnergy() > m_energyThTracker && isInsideTracker(track)) { //tracker* !!? + if (!m_cfTracker) { + setChordFinderForTracker(); + } + +<<<<<<< HEAD + } else if (track->GetKineticEnergy() <= m_energyThreshold || isInsideVacuum(track)) { //beampipe* +======= + } else if (track->GetKineticEnergy() <= m_energyThreshold || isInsideBeampipe(track)) { //beampipe* +>>>>>>> dedbbe927cafde8861ebe5968921156c3093037c + if (!m_cfBeampipe) { //beampipe* + setChordFinderForBeampipe(); //beampipe* + } + + } else if (m_cfTracker || m_cfBeampipe) { //tracker* !!? //beampipe* + // restore defaults + setDefaultChordFinder(); + } + } +<<<<<<< HEAD + bool ATLFieldManager::isInsideVacuum(const G4Track *track) { //beampipe* +======= +*/ +>>>>>>> 6b405a9246dbe177ebe3381b65003bcd666d7d18 void ATLFieldManager::ConfigureForTrack(const G4Track *track) { // run time parameters per track if (track->GetKineticEnergy() > m_energyThTracker && isInsideTracker(track)) { @@ -353,6 +403,7 @@ std::cout << "ccccccc" << ">\n"; } /* bool ATLFieldManager::isInsideBeampipe(const G4Track *track) { //beampipe* +>>>>>>> dedbbe927cafde8861ebe5968921156c3093037c if (!m_regions.empty()) { const G4Region *reg = track->GetVolume()->GetLogicalVolume()->GetRegion(); for (auto &areg : m_regions) { @@ -362,8 +413,17 @@ std::cout << "ccccccc" << ">\n"; } } return false; +<<<<<<< HEAD } */ bool ATLFieldManager::isInsideBeampipe(const G4Track *track) { +======= + } +<<<<<<< HEAD + +======= + */ + bool ATLFieldManager::isInsideBeampipe(const G4Track *track) { +>>>>>>> 6b405a9246dbe177ebe3381b65003bcd666d7d18 if (!m_regions.empty()) { const G4Region *reg = track->GetVolume()->GetLogicalVolume()->GetRegion(); @@ -397,13 +457,27 @@ bool ATLFieldManager::isInsideTracker(const G4Track *track) { } } return false; +<<<<<<< HEAD } /* +======= +} +*/ + /* +>>>>>>> dedbbe927cafde8861ebe5968921156c3093037c +>>>>>>> 6b405a9246dbe177ebe3381b65003bcd666d7d18 bool ATLFieldManager::isInsideTracker(const G4Track *track) { //tracker* !!? const G4ThreeVector &pos = track->GetPosition(); const double x = pos.x(); const double y = pos.y(); return (x * x + y * y < m_Rmax2 && std::abs(pos.z()) < m_Zmax); +<<<<<<< HEAD } */ +======= + } + + */ + +>>>>>>> 6b405a9246dbe177ebe3381b65003bcd666d7d18 void ATLFieldManager::setDefaultChordFinder() { if (m_currChordFinder != m_chordFinder) { m_currChordFinder = m_chordFinder; @@ -416,7 +490,7 @@ bool ATLFieldManager::isInsideTracker(const G4Track *track) { m_cfBeampipe = m_cfTracker = false; } - void ATLFieldManager::setChordFinderForTracker() { + void ATLFieldManager::setChordFinderForTracker() { if (m_currChordFinder != m_chordFinder) { m_currChordFinder = m_chordFinder; SetChordFinder(m_currChordFinder); @@ -429,7 +503,7 @@ bool ATLFieldManager::isInsideTracker(const G4Track *track) { m_cfTracker = true; } - void ATLFieldManager::setChordFinderForBeampipe() { + void ATLFieldManager::setChordFinderForBeampipe() { if (m_currChordFinder != m_chordFinder) { m_currChordFinder = m_chordFinder; SetChordFinder(m_currChordFinder); diff --git a/FullSimLight/src/FSLDetectorConstruction.cc b/FullSimLight/src/FSLDetectorConstruction.cc index 88b99cb4eecb9d699594b09418ce3959d01978fa..8e879694e4bd89b3b0b71d6a600039505b818b32 100644 --- a/FullSimLight/src/FSLDetectorConstruction.cc +++ b/FullSimLight/src/FSLDetectorConstruction.cc @@ -1,3 +1,7 @@ +/* + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration +*/ + #include "FSLDetectorConstruction.hh" #include "FSLDetectorMessenger.hh" #include "RegionConfigurator.hh" @@ -53,6 +57,34 @@ #include <cassert> +#include <algorithm> + +//chord +//#include "G4MagneticField.hh" +//#include "G4IntegrationDriver.hh" +//#include "G4VIntegrationDriver.hh" +//#include "G4MagIntegratorStepper.hh" +#include "G4Field.hh" +#include "G4VIntegrationDriver.hh" +#include "G4VIntegrationDriver.hh" +#include "G4FSALIntegrationDriver.hh" +#include "G4VFSALIntegrationStepper.hh" +#include "G4RK547FEq1.hh" +// #include "G4RK547FEq2.hh" +// #include "G4RK547FEq3.hh" +#include "G4NystromRK4.hh" + +// New FSAL type driver / steppers ----- +#include "G4IntegrationDriver.hh" +#include "G4InterpolationDriver.hh" +// #include "G4FSALBogackiShampine45.hh" +// #include "G4FSALDormandPrince745.hh" +#include "G4HelixHeum.hh" +#include "G4BFieldIntegrationDriver.hh" + +#include <cassert> + + // Geant4 steppers #if G4VERSION_NUMBER>=1040 #include "G4BogackiShampine23.hh" @@ -93,6 +125,8 @@ #include "GeoModelKernel/GeoVGeometryPlugin.h" #include "GeoModelKernel/GeoGeometryPluginLoader.h" #include "GeoModelKernel/GeoVolumeCursor.h" +#include "GeoModelKernel/GeoAlignableTransform.h" +#include "GeoModelFuncSnippets/defineWorld.h" // For Sensitive Detector plugins: #include "FullSimLight/FSLSensitiveDetectorPlugin.h" @@ -142,7 +176,7 @@ #include "G4StepLimiter.hh" //#include "StepMax.hh" #include <cassert> -#include "HistoManager.hh" + #include "G4FieldManagerStore.hh" #include "G4RegionStore.hh" @@ -187,38 +221,11 @@ FSLDetectorConstruction::~FSLDetectorConstruction() } -GeoPhysVol* FSLDetectorConstruction::CreateTheWorld(GeoPhysVol* world) -{ - if (world == nullptr) - { - // Setup the 'World' volume from which everything else will be suspended - // Get the materials that we shall use. - // -------------------------------------// - GeoMaterial* Air=new GeoMaterial("Air", 1.290*SYSTEM_OF_UNITS::mg/SYSTEM_OF_UNITS::cm3); - GeoElement* Oxigen = new GeoElement("Oxygen", "O", 8.0, 16.0*SYSTEM_OF_UNITS::g/SYSTEM_OF_UNITS::mole); - GeoElement* Nitrogen = new GeoElement("Nitrogen", "N", 7., 14.0067*SYSTEM_OF_UNITS::g/SYSTEM_OF_UNITS::mole); - -// GeoMaterial* Ether=new GeoMaterial("Ether", 1e-25*SYSTEM_OF_UNITS::g/SYSTEM_OF_UNITS::cm3); -// GeoElement* vacuum = new GeoElement("vacuum", "Mt", 1, 1); -// Ether->add(vacuum, 1.0); -// Ether->lock(); - - Air->add(Nitrogen, .8); - Air->add(Oxigen, .2); - Air->lock(); - const GeoBox* worldBox = new GeoBox(2000*SYSTEM_OF_UNITS::cm, 2000*SYSTEM_OF_UNITS::cm, 4000*SYSTEM_OF_UNITS::cm); - const GeoLogVol* worldLog = new GeoLogVol("WorldLog", worldBox, Air); - //const GeoLogVol* worldLog = new GeoLogVol("WorldLog", worldBox, Ether); - world = new GeoPhysVol(worldLog); - } - return world; -} - G4VPhysicalVolume *FSLDetectorConstruction::Construct() { fTimer.Start(); - GeoPhysVol* world = nullptr; + const GeoVPhysVol* world = nullptr; G4LogicalVolume* envelope; if (fGeometryFileName.contains(".dylib") || fGeometryFileName.contains(".so")) { @@ -230,9 +237,11 @@ G4VPhysicalVolume *FSLDetectorConstruction::Construct() exit(0); } - world = CreateTheWorld(nullptr); - factory->create(world); - + GeoIntrusivePtr<GeoPhysVol> worldTmp{createGeoWorld()}; + factory->create(worldTmp); + GeoIntrusivePtr<GeoPhysVol> world = resizeGeoWorld(worldTmp); + G4cout << "World resized correctly." << G4endl; + G4cout << "ReadGeoModel::buildGeoModel() done." << G4endl; fTimer.Stop(); G4cout << "First step done. GeoModelTree built from the SQLite file." << G4endl; @@ -242,7 +251,7 @@ G4VPhysicalVolume *FSLDetectorConstruction::Construct() fTimer.Start(); // build the Geant4 geometry and get an hanlde to the world' volume - ExtParameterisedVolumeBuilder* builder = new ExtParameterisedVolumeBuilder("ATLAS"); + ExtParameterisedVolumeBuilder* builder = new ExtParameterisedVolumeBuilder("Detector"); std::cout << "Building G4 geometry."<<std::endl; envelope = builder->Build(world); @@ -340,11 +349,19 @@ G4VPhysicalVolume *FSLDetectorConstruction::Construct() G4UserLimits* userLimits = new G4UserLimits(theStepMax); lv->SetUserLimits(userLimits); } +<<<<<<< HEAD // Print the value of maxStepLength (fStepMax) G4cout << "StepMax (fStepMax) set to: " << theStepMax << std::endl; +======= + + // Print the value of maxStepLength (fStepMax) + G4cout << "StepMax (fStepMax) set to: " << theStepMax << std::endl; + + +>>>>>>> dedbbe927cafde8861ebe5968921156c3093037c */ } else if (fGeometryFileName.contains(".gdml")){ @@ -561,6 +578,7 @@ if (fieldMgr) { // G4PropagatorInField* pf= new G4PropagatorInField(); G4PropagatorInField* pf= nullptr; // need to provide the actual propagator. +<<<<<<< HEAD // Call InitialiseForVolume with the correct parameters. atlFieldMgr->InitialiseForVolume(params, field, cfDefault, cfTracker, cfBeamPipe, vol, pf); @@ -569,6 +587,21 @@ if (fieldMgr) { } else { G4cerr << "Error: Failed to cast to ATLFieldManager." << G4endl; +======= +<<<<<<< HEAD + +////Tracker from CMS//////// +void G4FieldManager::ConfigureForTrack(const G4Track *ptrack) { + if (ptrack->GetKineticEnergy() // G4doc. < 2.5 * MeV )// { + TrackAndPrintParticleDetails(ptrack); + + if (!Tracker) { + setChordFinderForTracker(); + } + } else { + // restore defaults + setDefaultChordFinder(); +>>>>>>> 6b405a9246dbe177ebe3381b65003bcd666d7d18 } } else { G4cerr << "Error: No field manager associated with the geometry." << G4endl; @@ -588,8 +621,212 @@ if (fieldMgr) { } */ +<<<<<<< HEAD +//} //} +======= + // Loop through the logical volumes to find the SCT logical volume by name + for (auto lv : *logVolStore) { + if (lv->GetName() == G4String(sctName.c_str())) { // Convert std::string to G4String + sctLogicalVolume = lv; + break; + } + } + + // Check if the SCT logical volume was found + if (sctLogicalVolume) { + // Create a G4Region and associate it with the SCT logical volume + G4Region* sctRegion = new G4Region((sctName + "Region").c_str()); + sctRegion->AddRootLogicalVolume(sctLogicalVolume); + + // Set the step size limit for the SCT logical volume + G4double theStepMaxSCT = 2.0 * mm; // StepMax value for SCT + G4UserLimits* sctUserLimits = sctLogicalVolume->GetUserLimits(); + if (!sctUserLimits) { + sctUserLimits = new G4UserLimits(theStepMaxSCT); + sctLogicalVolume->SetUserLimits(sctUserLimits); + } else { + // If user limits already exist, update the maximum step length + sctUserLimits->SetMaxAllowedStep(theStepMaxSCT); + } + + // Print the step size limit for the SCT logical volume + G4cout << "Step size limit on " << sctName << ": " << theStepMaxSCT / mm << " mm" << G4endl; + } else { + G4cerr << "Error: Logical volume '" << sctName << "' not found in the geometry description!" << G4endl; + } +} +*/ + +///////////////////// + +/* +//G4double theStepMax = 1.0 * mm; +// Loop through logical volumes and set the step limits +for (auto lv : *logVolStore) { + G4UserLimits* userLimits = lv->GetUserLimits(); + if (!userLimits) { + userLimits = new G4UserLimits(theStepMax); + lv->SetUserLimits(userLimits); + } else { + // If user limits already exist, update the maximum step length + userLimits->SetMaxAllowedStep(theStepMax); + } +} +======= + +////Tracker from CMS//////// +void G4FieldManager::ConfigureForTrack(const G4Track *ptrack) { + if (ptrack->GetKineticEnergy() // G4doc. < 2.5 * MeV )// { + TrackAndPrintParticleDetails(ptrack); + + if (!Tracker) { + setChordFinderForTracker(); + } + } else { + // restore defaults + setDefaultChordFinder(); + } +} +*/ + +/*void G4UserSteppingAction::UserSteppingAction(const G4Step* step) { + G4Track* track = step->GetTrack(); + G4ParticleDefinition* particle = track->GetDefinition(); + G4ThreeVector position = track->GetPosition(); + G4ThreeVector momentum = track->GetMomentum(); + + G4cout << "Particle: " << particle->GetParticleName() << G4endl; + G4cout << "Position: " << position << G4endl; + G4cout << "Momentum: " << momentum << G4endl; + // Add more information as needed + + // Call base class method for processing further + G4UserSteppingAction::UserSteppingAction(step); +*/ +/*void G4FieldManager::TrackAndPrintParticleDetails(const G4Track* track) { + const G4ParticleDefinition* particleDefinition = track->GetParticleDefinition(); + const G4DynamicParticle* dynamicParticle = track->GetDynamicParticle(); + + G4cout << "Particle Details:" << G4endl; + G4cout << " Track ID: " << track->GetTrackID() << G4endl; + G4cout << " Particle Name: " << particleDefinition->GetParticleName() << G4endl; + G4cout << " Particle Mass: " << particleDefinition->GetPDGMass() / GeV << " GeV/c^2" << G4endl; + G4cout << " Kinetic Energy: " << track->GetKineticEnergy() / GeV << " GeV" << G4endl; + G4cout << " Momentum: " << track->GetMomentum() / GeV << " GeV/c" << G4endl; + G4cout << " Position: " << track->GetPosition() / mm << " mm" << G4endl; + G4cout << " Direction: " << track->GetMomentumDirection() << G4endl; + + G4cout << G4endl; +}*/ + + ///////////////////////////////////////////////////////////// +///////////// MuonSys ///////////// +/*G4LogicalVolume* muonSysLogicalVolume = nullptr; + +// Loop through the logical volumes to find "MuonSys" by name +for (auto lv : *logVolStore) { + if (lv->GetName() == "MuonSys") { + muonSysLogicalVolume = lv; + break; + } +} +////////////////////DeltaIntersection-MuonSys///////////// +// Check for "MuonSys" +if (muonSysLogicalVolume) { + // Create a G4Region and associate it with "MuonSys" logical volume + G4Region* muonSysRegion = new G4Region("MuonSysRegion"); + muonSysRegion->AddRootLogicalVolume(muonSysLogicalVolume); + + // Set the step size limit for "MuonSys" logical volume + G4double theStepMaxMuonSys = 1.0 * mm; // StepMax value for MuonSys + G4UserLimits* muonSysUserLimits = muonSysLogicalVolume->GetUserLimits(); + if (!muonSysUserLimits) { + muonSysUserLimits = new G4UserLimits(theStepMaxMuonSys); + muonSysLogicalVolume->SetUserLimits(muonSysUserLimits); + } else { + // If user limits already exist, update the maximum step length + muonSysUserLimits->SetMaxAllowedStep(theStepMaxMuonSys); + } + + // Get the field manager for the "MuonSysRegion" + G4FieldManager* muonSysFieldMgr = muonSysRegion->GetFieldManager(); + + // Set the deltaIntersection for the "MuonSysRegion" + G4double theDeltaIntersectionMuonSys = 0.1 * mm; // DeltaIntersection value for MuonSys + muonSysFieldMgr->SetDeltaIntersection(theDeltaIntersectionMuonSys); + + // Print the step size limit for "MuonSys" logical volume + G4cout << "Step size limit on MuonSys: " << theStepMaxMuonSys / mm << " mm" << G4endl; + // Print the deltaIntersection for "MuonSys" region + G4cout << "DeltaIntersection for MuonSysRegion: " << theDeltaIntersectionMuonSys / mm << " mm" << G4endl; + } else { + G4cerr << "Error: Logical volume 'MuonSys' not found in the geometry description!" << G4endl; + }*/ //} +///////////////////////////////////////////////////////// +///////////// SCT ///////////// +/* +// Create a list of SCT logical volume names +std::vector<std::string> sctLogicalVolumeNames = {"SCT_Barrel", "SCT_ForwardA", "SCT_ForwardC"}; + +for (const std::string& sctName : sctLogicalVolumeNames) { + G4LogicalVolume* sctLogicalVolume = nullptr; + + // Loop through the logical volumes to find the SCT logical volume by name + for (auto lv : *logVolStore) { + if (lv->GetName() == G4String(sctName.c_str())) { // Convert std::string to G4String + sctLogicalVolume = lv; + break; + } + } + + // Check if the SCT logical volume was found + if (sctLogicalVolume) { + // Create a G4Region and associate it with the SCT logical volume + G4Region* sctRegion = new G4Region((sctName + "Region").c_str()); + sctRegion->AddRootLogicalVolume(sctLogicalVolume); + + // Set the step size limit for the SCT logical volume + G4double theStepMaxSCT = 2.0 * mm; // StepMax value for SCT + G4UserLimits* sctUserLimits = sctLogicalVolume->GetUserLimits(); + if (!sctUserLimits) { + sctUserLimits = new G4UserLimits(theStepMaxSCT); + sctLogicalVolume->SetUserLimits(sctUserLimits); + } else { + // If user limits already exist, update the maximum step length + sctUserLimits->SetMaxAllowedStep(theStepMaxSCT); + } + + // Print the step size limit for the SCT logical volume + G4cout << "Step size limit on " << sctName << ": " << theStepMaxSCT / mm << " mm" << G4endl; + } else { + G4cerr << "Error: Logical volume '" << sctName << "' not found in the geometry description!" << G4endl; + } +} +*/ + +///////////////////// + +/* +//G4double theStepMax = 1.0 * mm; +// Loop through logical volumes and set the step limits +for (auto lv : *logVolStore) { + G4UserLimits* userLimits = lv->GetUserLimits(); + if (!userLimits) { + userLimits = new G4UserLimits(theStepMax); + lv->SetUserLimits(userLimits); + } else { + // If user limits already exist, update the maximum step length + userLimits->SetMaxAllowedStep(theStepMax); + } +} +>>>>>>> dedbbe927cafde8861ebe5968921156c3093037c + +// Print the value of maxStepLength (theStepMax) +G4cout << "StepMax (theStepMax) set to: " << theStepMax << std::endl; */ + +>>>>>>> 6b405a9246dbe177ebe3381b65003bcd666d7d18 // This is thread-local //To print the values of parameters fieldMgr = G4TransportationManager::GetTransportationManager()->GetFieldManager(); diff --git a/FullSimLight/src/MassCalculator.cc b/FullSimLight/src/MassCalculator.cc index b5e491fc6d5bab90ef18e9423a9eac6074bb776d..e7e8f5b8f27f35b25dbefb6efc736c470f19b917 100644 --- a/FullSimLight/src/MassCalculator.cc +++ b/FullSimLight/src/MassCalculator.cc @@ -1,3 +1,7 @@ +/* + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration +*/ + #include "MassCalculator.hh" #include "GeoModelKernel/GeoVolumeCursor.h" @@ -222,7 +226,7 @@ void MassCalculator::iterateFromWorldMass(G4LogicalVolume* logVolume, std::vecto } -void MassCalculator::recursiveMassCalculation (G4VPhysicalVolume* worldg4, GeoPhysVol* /*worldgeoModel*/, std::vector<json>& jlist){ +void MassCalculator::recursiveMassCalculation (G4VPhysicalVolume* worldg4, const GeoVPhysVol* /*worldgeoModel*/, std::vector<json>& jlist){ masscalc::massReport singleMassReport; json jSingleMassReport; diff --git a/GeoModelCore/.gitlab-ci.yml b/GeoModelCore/.gitlab-ci.yml index 01bd072504d072a97fdf3484ff0d5829574c06bc..e1cb2816969a63d98d0c9d0644746a08d4b8fa1a 100644 --- a/GeoModelCore/.gitlab-ci.yml +++ b/GeoModelCore/.gitlab-ci.yml @@ -68,6 +68,6 @@ deploying: "EOS_PATH": "/eos/project/g/geomodel/www/doxygen" image: gitlab-registry.cern.ch/ci-tools/ci-web-deployer only: - - master + - main script: - deploy-eos diff --git a/GeoModelCore/CMakeLists.txt b/GeoModelCore/CMakeLists.txt index 53c5de784abfc83e339d015d58cced12984e75cd..814e20f8db35c7897030b6e37787ea61f0f1251c 100644 --- a/GeoModelCore/CMakeLists.txt +++ b/GeoModelCore/CMakeLists.txt @@ -1,13 +1,14 @@ # Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration # Set up the (sub-)project. -cmake_minimum_required( VERSION 3.1 ) +cmake_minimum_required(VERSION 3.16...3.26) #project( "GeoModelCore" VERSION 4.1.0 LANGUAGES CXX ) project( "GeoModelCore" VERSION ${GeoModel_VERSION} LANGUAGES CXX ) # Set up the build of the two libraries of the (sub-)project. add_subdirectory( GeoGenericFunctions ) add_subdirectory( GeoModelKernel ) +add_subdirectory( GeoModelFuncSnippets ) # Create and install the version description of the project. include( WriteBasicConfigVersionFile ) diff --git a/GeoModelCore/GeoGenericFunctions/README.md b/GeoModelCore/GeoGenericFunctions/README.md index b99d2a3859a9430f4d83c218898d448a033f8ee4..cec5191d7fd40dd0cee7498950196b2cfc4e9901 100644 --- a/GeoModelCore/GeoGenericFunctions/README.md +++ b/GeoModelCore/GeoGenericFunctions/README.md @@ -21,7 +21,7 @@ make install Usually, Externals packages are buit and installed through the build of the package [atlasexternals](), downloading and compiling the sources of the different packages and installing them in an "install" folder, to let Athena-code uses them through a series of scripts. However, this implies that, if you change the source code of an External package, you must push your changes somewhere (or you must package them ina zip file) for the `atlasexternals` build script to get your latest changes. And that implies a series of additional steps, which are not convenient if you are actively debugging or developing code. -Thus, after having installed the `atlasexternals` as usual (let's assume, using the path `../../install/VP1LightExternals/` as `DISTDIR`; see the [atlasexternals docs](https://gitlab.cern.ch/atlas/atlasexternals/blob/master/README.md) for further details, or [this guide for developers](https://gitlab.cern.ch/atlas/atlasexternals/blob/master/CONTRIBUTING.md)), if you want to compile interacively this external while you are developing Athena or AnalysisBase/VP1Light packages, you can use these example commands (replace the paths with your own): +Thus, after having installed the `atlasexternals` as usual (let's assume, using the path `../../install/VP1LightExternals/` as `DISTDIR`; see the [atlasexternals docs](https://gitlab.cern.ch/atlas/atlasexternals/blob/main/README.md) for further details, or [this guide for developers](https://gitlab.cern.ch/atlas/atlasexternals/blob/main/CONTRIBUTING.md)), if you want to compile interacively this external while you are developing Athena or AnalysisBase/VP1Light packages, you can use these example commands (replace the paths with your own): ```bash diff --git a/GeoModelCore/GeoModelFuncSnippets/.DS_Store b/GeoModelCore/GeoModelFuncSnippets/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..ae5c8ecde22999e8b2b13eb4d697826d2742b328 Binary files /dev/null and b/GeoModelCore/GeoModelFuncSnippets/.DS_Store differ diff --git a/GeoModelCore/GeoModelFuncSnippets/CMakeLists.txt b/GeoModelCore/GeoModelFuncSnippets/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..e30ae17d92585799d0130a3af30c8dc09410c8ca --- /dev/null +++ b/GeoModelCore/GeoModelFuncSnippets/CMakeLists.txt @@ -0,0 +1,59 @@ +# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration + +# Find the header and source files. +file( GLOB SOURCES src/*.cxx ) +file( GLOB HEADERS GeoModelFuncSnippets/*.h GeoModelFuncSnippets/*.icc ) + +# Create the library. +add_library( GeoModelFuncSnippets SHARED ${HEADERS} ${SOURCES} ) + +target_link_libraries( GeoModelFuncSnippets PRIVATE GeoModelCore::GeoModelKernel ) + + +target_include_directories( GeoModelFuncSnippets PUBLIC + $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> + $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> ) +source_group( "GeoModelFuncSnippets" FILES ${HEADERS} ) +source_group( "src" FILES ${SOURCES} ) +set_target_properties( GeoModelFuncSnippets PROPERTIES + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR} ) + +# Set up an alias with the same name that you would get by "finding" a pre-built +# version of the library. +add_library( GeoModelCore::GeoModelFuncSnippets ALIAS GeoModelFuncSnippets ) + +# Install the library. +install(TARGETS GeoModelFuncSnippets + EXPORT ${PROJECT_NAME}-export + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + COMPONENT Runtime + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT Runtime + NAMELINK_COMPONENT Development # Requires CMake 3.12 + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT Development + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/GeoModelFuncSnippets + COMPONENT Development + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} +) + +install( FILES ${HEADERS} + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/GeoModelFuncSnippets + COMPONENT Development ) + +file(GLOB_RECURSE files "tests/*.cxx") +foreach(_exeFile ${files}) + get_filename_component(_theExec ${_exeFile} NAME_WE) + get_filename_component(_theLoc ${_exeFile} DIRECTORY) + + if(${_theLoc} MATCHES "DoNotBuild") + continue() + endif() + + add_executable(${_theExec} ${_exeFile}) + target_link_libraries( ${_theExec} GeoModelCore::GeoModelFuncSnippets GeoModelCore::GeoModelKernel) + add_test(NAME ${_theExec} + COMMAND ${_theExec}) + +endforeach() diff --git a/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/FileUtils.h b/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/FileUtils.h new file mode 100644 index 0000000000000000000000000000000000000000..89381e64ee39f8edda13ba2774e012e9ab33dad4 --- /dev/null +++ b/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/FileUtils.h @@ -0,0 +1,27 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ +#ifndef GEOMODELFUNCSNIPPETS_FILEUTILS_H +#define GEOMODELFUNCSNIPPETS_FILEUTILS_H + +#include <string> +#include <string_view> +#include <vector> + +namespace GeoFileUtils { + bool doesFileExist(const std::string_view path); + bool doesDirectoryExist(const std::string_view path); + bool mkdir(const std::string_view path); + + std::vector<std::string> listDirectory(const std::string_view path, + bool recursive = false); + + std::vector<std::string> findFile(const std::string_view path, + const std::string_view file); + + bool copyFile(const std::string_view from, + const std::string_view to); + + +} +#endif \ No newline at end of file diff --git a/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/GeoLogVolSorter.h b/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/GeoLogVolSorter.h new file mode 100644 index 0000000000000000000000000000000000000000..7dca5c7006624d8e70e3435da6a0eb5527708efe --- /dev/null +++ b/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/GeoLogVolSorter.h @@ -0,0 +1,40 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ +#ifndef GEOMODELFUNCSNIPPETS_GEOLOGVOLSORTER_H +#define GEOMODELFUNCSNIPPETS_GEOLOGVOLSORTER_H + +#include "GeoModelKernel/GeoLogVol.h" +#include "GeoModelKernel/GeoIntrusivePtr.h" + + +/* + * Helper struct to assess whether two logical volumes are the same allbeit they are + * different instances in memory. They're considered as the same if + * - Their GeoMaterial pointer is the same instance + * - The comparison of their shapes is equivalent +*/ +class GeoLogVolSorter { + public: + /** + * Comparison operator instantiated if std::set<> or std::map of + * GeoIntrusivePtr< (const) GeoIntrusivePtr> are defined + */ + template <class LogVolType> + bool operator()(const GeoIntrusivePtr<LogVolType>& a, + const GeoIntrusivePtr<LogVolType>& b) const{ + return (*this) (a.get(), b.get()); + } + /** + * Standard comparison operator between two volume instances. + * Returns true if the compare function returns a value < 0 + */ + bool operator()(const GeoLogVol* a, const GeoLogVol* b) const; + + /** @brief Compares two logical volumes + * 1) Check whether the material pointers are the same + * 2) Return the decision of the GeoShapeSorter + */ + int compare(const GeoLogVol*a, const GeoLogVol* b) const; +}; +#endif \ No newline at end of file diff --git a/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/GeoPhysVolSorter.h b/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/GeoPhysVolSorter.h new file mode 100644 index 0000000000000000000000000000000000000000..0612a7dcbfe20ccd808a275187ac04ddc12568b7 --- /dev/null +++ b/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/GeoPhysVolSorter.h @@ -0,0 +1,37 @@ + +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ +#ifndef GEOMODELFUNCSNIPPETS_GEOPHYSVOLSORTER_H +#define GEOMODELFUNCSNIPPETS_GEOPHYSVOLSORTER_H + +#include "GeoModelKernel/GeoVPhysVol.h" + +/** + * Helper struct to compare two physical volumes for the insertion into a set + * Two volumes are considered to be equal if they have: + * + * 1) Equivalent shapes + * 2) Same material pointer + * 3) Same number of children + * 4) Each child is placed at the same position inside the volume + * & points 1-3 hold for them as well + * + * The comparisons are not performed if one of the objects is a full physical volume. In this case, + * it simply falls back to an ordinary pointer address comparator. +*/ +struct GeoPhysVolSorter { + + template <class VolType> + bool operator()(const GeoIntrusivePtr<VolType>& a, + const GeoIntrusivePtr<VolType>& b) const{ + return compare(a, b) < 0; + } + + bool operator()(const GeoVPhysVol* a, const GeoVPhysVol* b) const { + return compare(a, b) < 0; + } + + int compare(const GeoVPhysVol*a, const GeoVPhysVol* b) const; +}; +#endif \ No newline at end of file diff --git a/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/GeoShapeSorter.h b/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/GeoShapeSorter.h new file mode 100644 index 0000000000000000000000000000000000000000..388348bec2102334401189f45c58cdb55f41e131 --- /dev/null +++ b/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/GeoShapeSorter.h @@ -0,0 +1,45 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ +#ifndef GEOMODELFUNCSNIPPETS_GeoShapeSorter_H +#define GEOMODELFUNCSNIPPETS_GeoShapeSorter_H + +#include "GeoModelKernel/GeoShape.h" +#include "GeoModelKernel/GeoIntrusivePtr.h" +#include <set> + +/// @brief Helper struct to construct set of GeoShapes where the defining parameters of +/// each element are unique within 1 micrometer +struct GeoShapeSorter { + template<class ShapeType1, class ShapeType2> + bool operator()(const GeoIntrusivePtr<ShapeType1>& a, + const GeoIntrusivePtr<ShapeType2>& b) const { + return (*this)(a.get(), b.get()); + } + + bool operator()(const GeoShape* a, const GeoShape* b) const; + /// @brief Compares 2 GeoShapes + /// @param a : Pointer to shape A + /// @param b : Pointer to shape B + /// @return Returns 0 if no defining shape property could be found that differs + /// Returns -1 if the first defining & differing property of A is smaller + /// Returns 1 otherwise + int compare(const GeoShape* a, const GeoShape* b) const; + +}; + +struct GeoComposedShapeSorter { + template<class ShapeType1, class ShapeType2> + bool operator()(const GeoIntrusivePtr<ShapeType1>& a, + const GeoIntrusivePtr<ShapeType2>& b) const { + return (*this)(a.get(), b.get()); + } + bool operator()(const GeoShape* a, const GeoShape* b) const; + +}; +/// @brief +/// @tparam ShapeType +template<class ShapeType> +using GeoShapeSet = std::set<GeoIntrusivePtr<const ShapeType>, GeoShapeSorter>; + +#endif \ No newline at end of file diff --git a/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/GeoShapeUtils.h b/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/GeoShapeUtils.h new file mode 100644 index 0000000000000000000000000000000000000000..2fe716d13dd137cd88ddc33933160b6519b7b801 --- /dev/null +++ b/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/GeoShapeUtils.h @@ -0,0 +1,30 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ +#ifndef GEOMDOELFUNCSNPPETS_PRINTSHAPE_H +#define GEOMDOELFUNCSNPPETS_PRINTSHAPE_H +#include "GeoModelKernel/GeoShape.h" +#include "GeoModelKernel/GeoIntrusivePtr.h" +#include <string> + +std::string printGeoShape(const GeoShape* shape); + + +/// Returns the sub operators of a GeoShape (GeoShapeUnion, GeoShapeSubtraction, GeoShapeUnion, GeoShapeShift) +std::pair<const GeoShape* , const GeoShape*> getOps(const GeoShape* composed); +/// Counts out of how many shapes the shape object is made up +unsigned int countComposedShapes(const GeoShape* shape); + + +/// @brief If a the operating shape of a ShapeShift is another ShapeShift a +/// new shapeShift is created with the combined transformation +GeoIntrusivePtr<const GeoShape> compressShift(const GeoShape* shift); + +/// @brief Returns all acting of coomponents of a BooleanVolume. +/// I.e. in case Of GeoShapeInterSection & GeoShapeUnion all building shape volumes +/// In the case of the GeoSubtraction all subtracting shapes +std::vector<const GeoShape*> getBooleanComponents(const GeoShape* booleanShape); + + + +#endif \ No newline at end of file diff --git a/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/StringUtils.h b/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/StringUtils.h new file mode 100644 index 0000000000000000000000000000000000000000..da93675a5aa3610c11c8c29eeb6a7c9b510271f9 --- /dev/null +++ b/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/StringUtils.h @@ -0,0 +1,66 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ +#ifndef GEOMODELFUNCSNIPPETS_STRINGUTILS_H +#define GEOMODELFUNCSNIPPETS_STRINGUTILS_H + +#include <string> +#include <string_view> +#include <vector> +#include <functional> + +namespace GeoStrUtils{ + + + /// @brief Replaces all occurances of pattern <A> by a substring <B> + /// @param str String to modify + /// @param exp Expression to be replaced + /// @param rep Replace it with + /// @return + std::string replaceExpInString(std::string str, + const std::string_view exp, + const std::string_view rep); + + /// @brief If a string contains a bash environment variable + /// E.g. ${GMX_FILES}/Blub.xml then the ${} expression is + /// replaced by the variable content + /// @param str + /// @return + std::string resolveEnviromentVariables(const std::string_view str); + + /// @brief returns the longest substring that's common between the + /// two given strings starting from character 0 + std::string_view longestCommonString(const std::string_view firstStr, + const std::string_view secondStr); + + /// @brief Returns a string consisting of N white spaces + std::string whiteSpaces(const unsigned int n, const std::string_view space =" "); + + /// Converts a string into an integer + int atoi(std::string_view str); + /// Converts a string into a double / float + double atof(std::string_view str); + /// Removes all trailing and starting whitespaces from a string + std::string_view eraseWhiteSpaces(std::string_view str); + + /// Splits the string into smaller substrings + std::vector<std::string> tokenize(const std::string& the_str, + std::string_view delimiter); + + std::vector<double> tokenizeDouble(const std::string& the_str, + std::string_view delimiter); + + std::vector<int> tokenizeInt(const std::string& the_str, + std::string_view delimiter); + + + template <class ObjType> std::string chainUp(unsigned int numEles, + const std::function<ObjType(unsigned int)>& func, + const std::string_view glue=";"); + + template <class ObjType> std::string chainUp(const std::vector<ObjType>& vector, + const std::string_view glue =";"); + +} +#include "GeoModelFuncSnippets/StringUtils.icc" +#endif \ No newline at end of file diff --git a/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/StringUtils.icc b/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/StringUtils.icc new file mode 100644 index 0000000000000000000000000000000000000000..aaae117703a59b5c76b30f01b7857576a71a265a --- /dev/null +++ b/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/StringUtils.icc @@ -0,0 +1,29 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ +#ifndef GEOMODELFUNCSNIPPETS_STRINGUTILS_ICC +#define GEOMODELFUNCSNIPPETS_STRINGUTILS_ICC + +#include <sstream> +namespace GeoStrUtils { + + + template <class ObjType> std::string chainUp(const std::vector<ObjType>& vector, + const std::string_view glue) { + return chainUp(vector.size(), [&vector](const unsigned int ele)->ObjType { + return vector.at(ele); + }, glue); + } + + template <class ObjType> std::string chainUp(unsigned int numEles, + const std::function<ObjType(unsigned int)>& func, + const std::string_view glue) { + std::stringstream chain{}; + for (unsigned int k =0; k < numEles; ++k) { + chain<<func(k); + if (k + 1 < numEles)chain<<glue; + } + return chain.str(); + } +} +#endif \ No newline at end of file diff --git a/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/TransformSorter.h b/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/TransformSorter.h new file mode 100644 index 0000000000000000000000000000000000000000..17693e891411617ae08646b6804223e0705fa1b0 --- /dev/null +++ b/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/TransformSorter.h @@ -0,0 +1,68 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ +#ifndef GEOMODELFUNCSNIPPETS_TRANSFORMSORTER_H +#define GEOMODELFUNCSNIPPETS_TRANSFORMSORTER_H + +#include "GeoModelKernel/GeoDefinitions.h" +#include "GeoModelKernel/GeoTransform.h" +#include "GeoModelKernel/GeoIntrusivePtr.h" +#include "GeoModelKernel/Units.h" + +#include <memory> + + +namespace GeoTrf { + /// @brief: Helper struct to construct sets of Tranform3D or sets of + /// smart pointers of Transform3D. Two Transforms are considered to + /// be equivalent if their translation difference is less + /// than 0.1 microns in each vector component and if their angles + /// coincide within 0.01 degrees. + struct TransformSorter { + + /// @brief Compare smart pointers of GeoTransforms + bool operator()(const std::unique_ptr<Transform3D>& a, + const std::unique_ptr<Transform3D>& b) const; + bool operator()(const std::shared_ptr<Transform3D>& a, + const std::shared_ptr<Transform3D>& b) const; + + + template<class GeoObjType> + bool operator()(const GeoIntrusivePtr<GeoObjType>& a, + const GeoIntrusivePtr<GeoObjType>& b) const { + return (*this) (a.get(), b.get()); + } + + bool operator()(const ::GeoTransform* a, + const ::GeoTransform* b) const; + + + bool operator()(const Transform3D& a, const Transform3D& b) const; + bool operator()(const RotationMatrix3D&a, const RotationMatrix3D& b) const; + + int compare(const Transform3D&a, const Transform3D& b) const; + int compare(const RotationMatrix3D&a, const RotationMatrix3D& b) const; + + /// @brief Compares two N-dimension vectors component wise + /// @param vecA Vector a to compare + /// @param vecB Vector b to compare + /// @return 0 if all components are the same within the tolerance + /// -1 if the first differing component of vecA is smaller than the one of vecB + /// 1 otherwise + template <int N> int compare(const VectorN<N>& vecA, const VectorN<N>& vecB) const { + constexpr double transTolerance = 0.1 * GeoModelKernelUnits::micrometer; + for (int d =0 ; d < N ; ++d) { + const double diffValue = vecA[d] - vecB[d]; + if (std::abs(diffValue) > transTolerance) { + return diffValue < 0. ? -1 : 1; + } + } + return 0; + } + template <int N> bool operator()(const VectorN<N>& vecA, const VectorN<N>& vecB) const { + return compare(vecA, vecB) < 0; + } + }; +} + +#endif \ No newline at end of file diff --git a/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/TransformToStringConverter.h b/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/TransformToStringConverter.h new file mode 100644 index 0000000000000000000000000000000000000000..62dfe421cdaaa321e2e36cb56cdf423ff2034d58 --- /dev/null +++ b/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/TransformToStringConverter.h @@ -0,0 +1,33 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ +#ifndef GEOMODELFUNCSNIPPETS_TRANSFORMTOSTRINGCONVERTER_H +#define GEOMODELFUNCSNIPPETS_TRANSFORMTOSTRINGCONVERTER_H +#include "GeoModelKernel/GeoDefinitions.h" + +#include <string> +#include <sstream> +#include <iomanip> +namespace GeoTrf{ + + template <int N> + inline std::string toString(const VectorN<N>& vector, int precision = 4) { + std::stringstream sout; + sout << std::setiosflags(std::ios::fixed) << std::setprecision(precision); + sout << "("; + for (int i = 0; i < N; ++i) { + sout << vector[i]; + if (i != N - 1) { + sout << ", "; + } + } + sout << ")"; + return sout.str(); + } + + std::string toString(const Transform3D& trans, bool useCoordAngles = false, int precision = 4); + std::string toString(const EulerAngles& angles, int precision = 4); + std::string toString(const CoordEulerAngles& angles, int precision = 4); +} + +#endif \ No newline at end of file diff --git a/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/defineWorld.h b/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/defineWorld.h new file mode 100644 index 0000000000000000000000000000000000000000..fbfe4779d63c9672a6e73795a2e146ec3e0f9118 --- /dev/null +++ b/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/defineWorld.h @@ -0,0 +1,25 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ +#ifndef GEOMODELUTILS_DEFINEWORLD_H +#define GEOMODELUTILS_DEFINEWORLD_H + +#include "GeoModelKernel/GeoPhysVol.h" +#include "GeoModelKernel/Units.h" + +/// @brief Common helper function that creates the top GeoWorld volume in the tree. +/// @returns A physical volume serving as world volume +namespace GeoWorldDim { + constexpr double worldBoxX = 20. * GeoModelKernelUnits::m; + constexpr double worldBoxY = 20. * GeoModelKernelUnits::m; + constexpr double worldBoxZ = 25. * GeoModelKernelUnits::m; +} + +/// Creates the basic GeoWorld +GeoIntrusivePtr<GeoPhysVol> createGeoWorld(const double worldBoxX = GeoWorldDim::worldBoxX, + const double worldBoxY = GeoWorldDim::worldBoxY, + const double worldBoxZ = GeoWorldDim::worldBoxZ); + +/// Resize the world volume to be the needed size +GeoIntrusivePtr<GeoPhysVol> resizeGeoWorld(GeoIntrusivePtr<GeoPhysVol> world); +#endif diff --git a/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/getChildNodesWithTrf.h b/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/getChildNodesWithTrf.h new file mode 100644 index 0000000000000000000000000000000000000000..78e79a6b8e599fbcc2ba08eaaeb1312ac84af443 --- /dev/null +++ b/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/getChildNodesWithTrf.h @@ -0,0 +1,39 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ +#ifndef GEOMDOELFUNCSNPPETS_GETCHILDNODESWITHTF_H +#define GEOMDOELFUNCSNPPETS_GETCHILDNODESWITHTF_H + +#include "GeoModelKernel/GeoVPhysVol.h" +#include "GeoModelKernel/GeoDefinitions.h" + + +class GeoVolumeCursor; + +struct GeoChildNodeWithTrf { + + /// @brief Transformation to the child node + GeoTrf::Transform3D transform{GeoTrf::Transform3D::Identity()}; + /// @brief In cases of multiple copies. What's the transformation + /// to go from n --> n+1 + GeoTrf::Transform3D inductionRule{GeoTrf::Transform3D::Identity()}; + /// @brief Physical volume pointer to the child + PVConstLink volume{}; + /// @brief Name of the physical volume empty if cursor finds ANON + std::string nodeName{}; + /// @brief How many times is the volume placed in the child tree + unsigned int nCopies{1}; + /// @brief tag whether the transformation is alignable + bool isAlignable{false}; + /// @brief tag whether the physical volume is a full physVol + bool isSensitive{false}; + + GeoChildNodeWithTrf() = default; + GeoChildNodeWithTrf(GeoVolumeCursor& curs); +}; + +std::vector <GeoChildNodeWithTrf> getChildrenWithRef (PVConstLink& physVol, + bool summarizeEqualVol = true); + + +#endif \ No newline at end of file diff --git a/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/throwExcept.h b/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/throwExcept.h new file mode 100644 index 0000000000000000000000000000000000000000..7be2db17993584667dc5005f3cc78fc831f591c6 --- /dev/null +++ b/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/throwExcept.h @@ -0,0 +1,17 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ +#ifndef GEOMODELFUNCSNIPPETS_THROWEXCEPT_H +#define GEOMODELFUNCSNIPPETS_THROWEXCEPT_H + +#include <exception> +#include <sstream> + +#define THROW_EXCEPTION(MESSAGE) \ + { \ + std::stringstream except_str{}; \ + except_str<<__FILE__<<":"<<__LINE__<<" --- "; \ + except_str<<MESSAGE; \ + throw std::runtime_error(except_str.str()); \ + } +#endif \ No newline at end of file diff --git a/GeoModelCore/GeoModelFuncSnippets/src/FileUtils.cxx b/GeoModelCore/GeoModelFuncSnippets/src/FileUtils.cxx new file mode 100644 index 0000000000000000000000000000000000000000..08b2c2fc3f59bab7d487d65798aedf6d36b1450f --- /dev/null +++ b/GeoModelCore/GeoModelFuncSnippets/src/FileUtils.cxx @@ -0,0 +1,79 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ +#include "GeoModelFuncSnippets/FileUtils.h" +#include "GeoModelFuncSnippets/StringUtils.h" + + +#include <filesystem> +#include <iostream> +#include <functional> +using namespace GeoStrUtils; + +namespace GeoFileUtils { + bool doesFileExist(const std::string_view path) { + const std::filesystem::path filePath{resolveEnviromentVariables(path)}; + return std::filesystem::exists(filePath) && std::filesystem::is_regular_file(filePath); + } + + bool doesDirectoryExist(const std::string_view path) { + const std::filesystem::path dirPath{resolveEnviromentVariables(path)}; + return std::filesystem::exists(dirPath) && std::filesystem::is_directory(dirPath); + } + + bool mkdir(const std::string_view path) { + std::filesystem::create_directories(resolveEnviromentVariables(path)); + return doesDirectoryExist(path); + } + + std::vector<std::string> listDirectory(const std::string_view path, + bool recursive) { + const std::filesystem::path dirPath{resolveEnviromentVariables(path)}; + + if (!doesDirectoryExist(path)) { + std::cout<<"WARNING - No directory "<<dirPath<<std::endl; + return {}; + } + std::vector<std::string> contents{}; + if (recursive){ + for (const auto& entry: std::filesystem::recursive_directory_iterator{dirPath}){ + contents.emplace_back(entry.path()); + } + } else { + for (const auto& entry: std::filesystem::directory_iterator{dirPath}){ + contents.emplace_back(entry.path()); + } + } + return contents; + } + std::vector<std::string> findFile(const std::string_view path, + const std::string_view file) { + + std::vector<std::string> foundFiles{}; + std::vector<std::string> contents{listDirectory(path, true)}; + std::copy_if(contents.begin(), contents.end(), + std::back_inserter(foundFiles), + [file](const std::string& entry) { + return entry.find(file) != std::string::npos; + }); + return foundFiles; + } + + bool copyFile(const std::string_view from, + const std::string_view to) { + + if (!doesFileExist(from)) { + std::cerr<<"copyFile() -- File "<<from<<" does not exist"<<std::endl; + return false; + } + if (to.find("/") != std::string::npos) { + if (!mkdir(to.substr(0, to.rfind("/")))){ + std::cerr<<"copyFile() -- Cannot create directory " + <<to.substr(0, to.rfind("/"))<<"."; + } + } + std::filesystem::copy(from, to, std::filesystem::copy_options::overwrite_existing); + return doesFileExist(to); + } + +} diff --git a/GeoModelCore/GeoModelFuncSnippets/src/GeoLogVolSorter.cxx b/GeoModelCore/GeoModelFuncSnippets/src/GeoLogVolSorter.cxx new file mode 100644 index 0000000000000000000000000000000000000000..592349222e004264cff0e33c2b7d04d1b53a5682 --- /dev/null +++ b/GeoModelCore/GeoModelFuncSnippets/src/GeoLogVolSorter.cxx @@ -0,0 +1,20 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ +#include "GeoModelFuncSnippets/GeoLogVolSorter.h" +#include "GeoModelFuncSnippets/throwExcept.h" +#include "GeoModelFuncSnippets/GeoShapeSorter.h" + +bool GeoLogVolSorter::operator()(const GeoLogVol* a, const GeoLogVol* b) const{ + return compare(a, b) < 0; +} +int GeoLogVolSorter::compare(const GeoLogVol*a, const GeoLogVol* b) const{ + if (!a || !b) { + THROW_EXCEPTION("Nullptr given to the comparator"); + } + if (a->getMaterial() != b->getMaterial()) { + return a->getMaterial()->getName() < b->getMaterial()->getName() ? -1 : 1; + } + static const GeoShapeSorter shapeSorter{}; + return shapeSorter.compare(a->getShape(), b->getShape()); +} diff --git a/GeoModelCore/GeoModelFuncSnippets/src/GeoPhysVolSorter.cxx b/GeoModelCore/GeoModelFuncSnippets/src/GeoPhysVolSorter.cxx new file mode 100644 index 0000000000000000000000000000000000000000..4ed7551232f5deefd044656a50d1273df4cc2196 --- /dev/null +++ b/GeoModelCore/GeoModelFuncSnippets/src/GeoPhysVolSorter.cxx @@ -0,0 +1,57 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ +#include "GeoModelFuncSnippets/GeoPhysVolSorter.h" +#include "GeoModelKernel/GeoFullPhysVol.h" + +#include "GeoModelFuncSnippets/TransformSorter.h" +#include "GeoModelFuncSnippets/GeoLogVolSorter.h" +#include "GeoModelKernel/GeoVolumeCursor.h" +#include "GeoModelFuncSnippets/getChildNodesWithTrf.h" + +int GeoPhysVolSorter::compare(const GeoVPhysVol* a, const GeoVPhysVol* b) const { + /// If one of the given volumes is a full physical volume, let's assume that they've been + /// put on purpose into the node. Ensure that they're added to the set eventhough they + /// are equivalent in the terms of this sorter. + if (typeid(*a) == typeid(GeoFullPhysVol) || typeid(*b) == typeid(GeoFullPhysVol)) { + return a < b; + } + + /// A check on different logical volumes is already a good start + { + static const GeoLogVolSorter sorter{}; + const int shapeCmp = sorter.compare(a->getLogVol(), b->getLogVol()); + if (shapeCmp) return shapeCmp; + } + + static const GeoTrf::TransformSorter sorter{}; + + GeoVolumeCursor cursA{a}, cursB{b}; + while (!cursA.atEnd() && !cursB.atEnd()) { + + GeoChildNodeWithTrf childA{cursA}; + GeoChildNodeWithTrf childB{cursB}; + cursA.next(); + cursB.next(); + /// Check whether there's an alignable transform somewhere + if (childA.isAlignable != childB.isAlignable) { + return childA.isAlignable; + } + /// Check whether the voumes are full physical volumes + if (childA.isSensitive != childB.isSensitive) { + return childA.isSensitive; + } + /// Check equivalance of the transformations + const int transCmp = sorter.compare(childA.transform, + childB.transform); + if (transCmp) return transCmp; + /// Every day greets the marmot + const int childCmp = compare(childA.volume, childB.volume); + if (childCmp) return childCmp; + } + if (cursA.atEnd() != cursB.atEnd()) { + if (cursA.atEnd()) return -1; + return 1; + } + return 0; +} \ No newline at end of file diff --git a/GeoModelCore/GeoModelFuncSnippets/src/GeoShapeSorter.cxx b/GeoModelCore/GeoModelFuncSnippets/src/GeoShapeSorter.cxx new file mode 100644 index 0000000000000000000000000000000000000000..1bd89c0d5af9c79aa44a01d46524032ea19e6134 --- /dev/null +++ b/GeoModelCore/GeoModelFuncSnippets/src/GeoShapeSorter.cxx @@ -0,0 +1,238 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ +#include "GeoModelFuncSnippets/GeoShapeSorter.h" +#include "GeoModelFuncSnippets/TransformSorter.h" +#include "GeoModelFuncSnippets/TransformToStringConverter.h" +#include "GeoModelFuncSnippets/GeoShapeUtils.h" +#include "GeoModelFuncSnippets/throwExcept.h" + +#include "GeoModelKernel/Units.h" + +#include "GeoModelKernel/GeoShapeUnion.h" +#include "GeoModelKernel/GeoShapeSubtraction.h" +#include "GeoModelKernel/GeoShapeIntersection.h" +#include "GeoModelKernel/GeoShapeShift.h" + + +#include "GeoModelKernel/GeoBox.h" +#include "GeoModelKernel/GeoTrd.h" +#include "GeoModelKernel/GeoTube.h" +#include "GeoModelKernel/GeoTubs.h" +#include "GeoModelKernel/GeoCons.h" +#include "GeoModelKernel/GeoEllipticalTube.h" +#include "GeoModelKernel/GeoPara.h" +#include "GeoModelKernel/GeoPcon.h" +#include "GeoModelKernel/GeoGenericTrap.h" +#include "GeoModelKernel/GeoPgon.h" +#include "GeoModelKernel/GeoSimplePolygonBrep.h" +#include "GeoModelKernel/GeoTorus.h" +#include "GeoModelKernel/GeoTrap.h" +#include "GeoModelKernel/GeoTwistedTrap.h" + +#include <exception> +#include <sstream> +#include <iostream> + +namespace { + constexpr double tolerance = 1.* GeoModelKernelUnits::micrometer; + static const GeoTrf::TransformSorter transCmp{}; +} + +#define CHECK_PROPERTY(shapeA, shapeB, PROP_NAME) \ + { \ + const double diffValue = 1.*shapeA->PROP_NAME() - \ + 1.*shapeB->PROP_NAME(); \ + if (std::abs(diffValue) > tolerance) { \ + return diffValue < 0 ? - 1 : 1; \ + } \ + } \ + +#define CHECK_VEC_PROPERTY(shapeA, shapeB, PROP_NAME, nChecks) \ + { \ + for(unsigned int n = 0 ; n < nChecks; ++n) { \ + const double diffValue = 1.*shapeA->PROP_NAME(n) - \ + 1.*shapeB->PROP_NAME(n); \ + \ + if (std::abs(diffValue) > tolerance) { \ + return diffValue < 0 ? - 1 : 1; \ + } \ + } \ + } + +#define CALL_SORTER(shapeA, shapeB) \ + { \ + const int cmpAB{compare(shapeA, shapeB)}; \ + if (cmpAB) return cmpAB; \ + } + +bool GeoShapeSorter::operator()(const GeoShape* objA, const GeoShape* objB) const { + if (!objA || !objB) { + THROW_EXCEPTION("Nullptr given to the comparator"); + } + return compare(objA, objB) < 0; +} + +int GeoShapeSorter::compare(const GeoShape* objA, const GeoShape* objB) const { + CHECK_PROPERTY(objA, objB, typeID); + /// Check the defining parameters of each shape one by one + const int typeID = objA->typeID(); + if (typeID == GeoShapeUnion::getClassTypeID() || + typeID == GeoShapeIntersection::getClassTypeID() || + typeID == GeoShapeSubtraction::getClassTypeID()) { + + std::pair<const GeoShape*, const GeoShape*> shapeOpsA{getOps(objA)}; + std::pair<const GeoShape*, const GeoShape*> shapeOpsB{getOps(objB)}; + CALL_SORTER(shapeOpsA.first, shapeOpsB.first); + CALL_SORTER(shapeOpsA.second, shapeOpsB.second); + } + /// + else if (typeID == GeoShapeShift::getClassTypeID()) { + const GeoShapeShift* shapeA = dynamic_cast<const GeoShapeShift*>(objA); + const GeoShapeShift* shapeB = dynamic_cast<const GeoShapeShift*>(objB); + const int xCmp = transCmp.compare(shapeA->getX(), shapeB->getX()); + if (xCmp) { + return xCmp; + } + CALL_SORTER(shapeA->getOp(), shapeB->getOp()); + } + else if (typeID == GeoBox::getClassTypeID()) { + const GeoBox* boxA = dynamic_cast<const GeoBox*>(objA); + const GeoBox* boxB = dynamic_cast<const GeoBox*>(objB); + CHECK_PROPERTY(boxA, boxB, getXHalfLength); + CHECK_PROPERTY(boxA, boxB, getYHalfLength); + CHECK_PROPERTY(boxA, boxB, getZHalfLength); + } else if (typeID == GeoTrd::getClassTypeID()) { + const GeoTrd* trdA = dynamic_cast<const GeoTrd*>(objA); + const GeoTrd* trdB = dynamic_cast<const GeoTrd*>(objB); + CHECK_PROPERTY(trdA, trdB, getXHalfLength1); + CHECK_PROPERTY(trdA, trdB, getXHalfLength2); + CHECK_PROPERTY(trdA, trdB, getYHalfLength1); + CHECK_PROPERTY(trdA, trdB, getYHalfLength2); + CHECK_PROPERTY(trdA, trdB, getZHalfLength); + } else if (typeID == GeoTube::getClassTypeID()) { + const GeoTube* tubeA = dynamic_cast<const GeoTube*>(objA); + const GeoTube* tubeB = dynamic_cast<const GeoTube*>(objB); + CHECK_PROPERTY(tubeA, tubeB, getRMin); + CHECK_PROPERTY(tubeA, tubeB, getRMax); + CHECK_PROPERTY(tubeA, tubeB, getZHalfLength); + } else if (typeID == GeoTubs::getClassTypeID()) { + const GeoTubs* tubeA = dynamic_cast<const GeoTubs*>(objA); + const GeoTubs* tubeB = dynamic_cast<const GeoTubs*>(objB); + CHECK_PROPERTY(tubeA, tubeB, getRMin); + CHECK_PROPERTY(tubeA, tubeB, getRMax); + CHECK_PROPERTY(tubeA, tubeB, getZHalfLength); + CHECK_PROPERTY(tubeA, tubeB, getSPhi); + CHECK_PROPERTY(tubeA, tubeB, getDPhi); + } else if (typeID == GeoCons::getClassTypeID()) { + const GeoCons* consA = dynamic_cast<const GeoCons*>(objA); + const GeoCons* consB = dynamic_cast<const GeoCons*>(objB); + CHECK_PROPERTY(consA, consB, getRMin1); + CHECK_PROPERTY(consA, consB, getRMin2); + CHECK_PROPERTY(consA, consB, getRMin1); + CHECK_PROPERTY(consA, consB, getRMax1); + CHECK_PROPERTY(consA, consB, getRMax2); + CHECK_PROPERTY(consA, consB, getDZ); + CHECK_PROPERTY(consA, consB, getSPhi); + CHECK_PROPERTY(consA, consB, getDPhi); + } else if (typeID == GeoEllipticalTube::getClassTypeID()) { + const GeoEllipticalTube* tubeA = dynamic_cast<const GeoEllipticalTube*>(objA); + const GeoEllipticalTube* tubeB = dynamic_cast<const GeoEllipticalTube*>(objB); + CHECK_PROPERTY(tubeA, tubeB, getXHalfLength); + CHECK_PROPERTY(tubeA, tubeB, getYHalfLength); + CHECK_PROPERTY(tubeA, tubeB, getZHalfLength); + } else if (typeID == GeoPara::getClassTypeID()) { + const GeoPara* paraA = dynamic_cast<const GeoPara*>(objA); + const GeoPara* paraB = dynamic_cast<const GeoPara*>(objB); + CHECK_PROPERTY(paraA, paraB, getXHalfLength); + CHECK_PROPERTY(paraA, paraB, getYHalfLength); + CHECK_PROPERTY(paraA, paraB, getZHalfLength); + CHECK_PROPERTY(paraA, paraB, getTheta); + CHECK_PROPERTY(paraA, paraB, getAlpha); + CHECK_PROPERTY(paraA, paraB, getPhi); + } else if (typeID == GeoGenericTrap::getClassTypeID()) { + const GeoGenericTrap* trapA = dynamic_cast<const GeoGenericTrap*>(objA); + const GeoGenericTrap* trapB = dynamic_cast<const GeoGenericTrap*>(objB); + CHECK_PROPERTY(trapA, trapB, getZHalfLength); + CHECK_PROPERTY(trapA, trapB, getVertices().size); + for (size_t v = 0; v < trapA->getVertices().size(); ++v) { + if (transCmp(trapA->getVertices()[v], trapB->getVertices()[v])) return true; + } + } else if (typeID == GeoPcon::getClassTypeID()) { + const GeoPcon* pconA = dynamic_cast<const GeoPcon*>(objA); + const GeoPcon* pconB = dynamic_cast<const GeoPcon*>(objB); + CHECK_PROPERTY(pconA, pconB, getNPlanes); + CHECK_PROPERTY(pconA, pconB, getSPhi); + CHECK_PROPERTY(pconA, pconB, getDPhi); + CHECK_VEC_PROPERTY(pconA, pconB, getZPlane, pconA->getNPlanes()); + CHECK_VEC_PROPERTY(pconA, pconB, getRMinPlane, pconA->getNPlanes()); + CHECK_VEC_PROPERTY(pconA, pconB, getRMaxPlane, pconA->getNPlanes()); + } else if (typeID == GeoPgon::getClassTypeID()) { + const GeoPgon* pgonA = dynamic_cast<const GeoPgon*>(objA); + const GeoPgon* pgonB = dynamic_cast<const GeoPgon*>(objB); + CHECK_PROPERTY(pgonA, pgonB, getNPlanes); + CHECK_PROPERTY(pgonA, pgonB, getNSides); + CHECK_PROPERTY(pgonA, pgonB, getSPhi); + CHECK_PROPERTY(pgonA, pgonB, getDPhi); + CHECK_VEC_PROPERTY(pgonA, pgonB, getZPlane, pgonA->getNPlanes()); + CHECK_VEC_PROPERTY(pgonA, pgonB, getRMinPlane, pgonA->getNPlanes()); + CHECK_VEC_PROPERTY(pgonA, pgonB, getRMaxPlane, pgonA->getNPlanes()); + } else if (typeID == GeoSimplePolygonBrep::getClassTypeID()) { + const GeoSimplePolygonBrep* brepA = dynamic_cast<const GeoSimplePolygonBrep*>(objA); + const GeoSimplePolygonBrep* brepB = dynamic_cast<const GeoSimplePolygonBrep*>(objB); + CHECK_PROPERTY(brepA, brepB, getNVertices); + CHECK_PROPERTY(brepA, brepB, getDZ); + CHECK_VEC_PROPERTY(brepA, brepB, getXVertex, brepA->getNVertices()); + CHECK_VEC_PROPERTY(brepA, brepB, getYVertex, brepA->getNVertices()); + } else if (typeID == GeoTorus::getClassTypeID()) { + const GeoTorus* torA = dynamic_cast<const GeoTorus*>(objA); + const GeoTorus* torB = dynamic_cast<const GeoTorus*>(objB); + CHECK_PROPERTY(torA, torB, getRMin); + CHECK_PROPERTY(torA, torB, getRMax); + CHECK_PROPERTY(torA, torB, getRTor); + CHECK_PROPERTY(torA, torB, getSPhi); + CHECK_PROPERTY(torA, torB, getDPhi); + } else if (typeID == GeoTrap::getClassTypeID()) { + const GeoTrap* trapA = dynamic_cast<const GeoTrap*>(objA); + const GeoTrap* trapB = dynamic_cast<const GeoTrap*>(objB); + CHECK_PROPERTY(trapA, trapB, getZHalfLength); + CHECK_PROPERTY(trapA, trapB, getTheta); + CHECK_PROPERTY(trapA, trapB, getPhi); + CHECK_PROPERTY(trapA, trapB, getDydzn); + CHECK_PROPERTY(trapA, trapB, getDxdyndzn); + CHECK_PROPERTY(trapA, trapB, getDxdypdzn); + CHECK_PROPERTY(trapA, trapB, getAngleydzn); + CHECK_PROPERTY(trapA, trapB, getDydzp); + CHECK_PROPERTY(trapA, trapB, getDxdyndzp); + CHECK_PROPERTY(trapA, trapB, getDxdypdzp); + CHECK_PROPERTY(trapA, trapB, getAngleydzp); + } else if (typeID == GeoTwistedTrap::getClassTypeID()) { + const GeoTwistedTrap* trapA = dynamic_cast<const GeoTwistedTrap*>(objA); + const GeoTwistedTrap* trapB = dynamic_cast<const GeoTwistedTrap*>(objB); + CHECK_PROPERTY(trapA, trapB, getY1HalfLength); + CHECK_PROPERTY(trapA, trapB, getX1HalfLength); + CHECK_PROPERTY(trapA, trapB, getX2HalfLength); + CHECK_PROPERTY(trapA, trapB, getY2HalfLength); + CHECK_PROPERTY(trapA, trapB, getX3HalfLength); + CHECK_PROPERTY(trapA, trapB, getX4HalfLength); + CHECK_PROPERTY(trapA, trapB, getZHalfLength); + CHECK_PROPERTY(trapA, trapB, getPhiTwist); + CHECK_PROPERTY(trapA, trapB, getTheta); + CHECK_PROPERTY(trapA, trapB, getPhi); + CHECK_PROPERTY(trapA, trapB, getTiltAngleAlpha); + } else { + THROW_EXCEPTION("The shape "<<objA->type()<<" has not yet been implemented into the sorter"); + } + return 0; +} + +bool GeoComposedShapeSorter::operator()(const GeoShape* a, const GeoShape* b) const { + const unsigned int aComposed{countComposedShapes(a)}; + const unsigned int bComposed{countComposedShapes(b)}; + if (aComposed != bComposed) return aComposed < bComposed; + return a->typeID() < b->typeID(); +} +#undef CHECK_PROPERTY +#undef CHECK_VEC_PROPERTY +#undef COMPARE_GEOVEC +#undef CALL_SORTER \ No newline at end of file diff --git a/GeoModelCore/GeoModelFuncSnippets/src/GeoShapeUtils.cxx b/GeoModelCore/GeoModelFuncSnippets/src/GeoShapeUtils.cxx new file mode 100644 index 0000000000000000000000000000000000000000..4ba5bffcb0eb43375ab05daebe600bdfa756beec --- /dev/null +++ b/GeoModelCore/GeoModelFuncSnippets/src/GeoShapeUtils.cxx @@ -0,0 +1,141 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ +#include "GeoModelFuncSnippets/GeoShapeUtils.h" +#include "GeoModelFuncSnippets/TransformToStringConverter.h" + +/// Boolean volume shapes +#include "GeoModelKernel/GeoShapeUnion.h" +#include "GeoModelKernel/GeoShapeSubtraction.h" +#include "GeoModelKernel/GeoShapeIntersection.h" +#include "GeoModelKernel/GeoShapeShift.h" +#include "GeoModelKernel/GeoShape.h" +/// Ordinary shapes +#include "GeoModelKernel/GeoBox.h" +#include "GeoModelKernel/GeoTrd.h" +#include "GeoModelKernel/GeoTube.h" +#include "GeoModelKernel/GeoTubs.h" +#include "GeoModelKernel/GeoEllipticalTube.h" +#include "GeoModelKernel/GeoCons.h" +#include "GeoModelKernel/GeoPara.h" +#include "GeoModelKernel/GeoTorus.h" + +#include "GeoModelKernel/Units.h" + +#include <vector> + +std::pair<const GeoShape* , const GeoShape*> getOps(const GeoShape* composed) { + if (composed->typeID() == GeoShapeUnion::getClassTypeID()) { + const GeoShapeUnion* unionShape = dynamic_cast<const GeoShapeUnion*>(composed); + return std::make_pair(unionShape->getOpA(), unionShape->getOpB()); + } else if (composed->typeID() == GeoShapeSubtraction::getClassTypeID()) { + const GeoShapeSubtraction* shapeSubtract = dynamic_cast<const GeoShapeSubtraction*>(composed); + return std::make_pair(shapeSubtract->getOpA(), shapeSubtract->getOpB()); + } else if (composed->typeID() == GeoShapeUnion::getClassTypeID()) { + const GeoShapeIntersection* shapeIntersect = dynamic_cast<const GeoShapeIntersection*>(composed); + return std::make_pair(shapeIntersect->getOpA(), shapeIntersect->getOpB()); + } else if (composed->typeID() == GeoShapeShift::getClassTypeID()) { + const GeoShapeShift* shapeShift = dynamic_cast<const GeoShapeShift*>(composed); + return std::make_pair(shapeShift->getOp(), nullptr); + } + return std::make_pair(nullptr, nullptr); +} + +unsigned int countComposedShapes(const GeoShape* shape) { + std::pair<const GeoShape*, const GeoShape*> ops = getOps(shape); + return 1 + (ops.first ? countComposedShapes(ops.first) : 0) + + (ops.second ? countComposedShapes(ops.second) : 0); +} + +GeoIntrusivePtr<const GeoShape> compressShift(const GeoShape* shift) { + if (shift->typeID() != GeoShapeShift::getClassTypeID()) return GeoIntrusivePtr<const GeoShape>{shift}; + const GeoShapeShift* shapeShift = dynamic_cast<const GeoShapeShift*>(shift); + if (shapeShift->getOp()->typeID() != GeoShapeShift::getClassTypeID()) return GeoIntrusivePtr<const GeoShape>{shift}; + GeoIntrusivePtr<const GeoShape> subShape{compressShift(shapeShift->getOp())}; + const GeoShapeShift* subShift = dynamic_cast<const GeoShapeShift*>(subShape.get()); + return GeoIntrusivePtr<const GeoShape>{new GeoShapeShift(subShift->getOp(), subShift->getX() * shapeShift->getX())}; +} +std::vector<const GeoShape*> getBooleanComponents(const GeoShape* booleanShape) { + std::pair<const GeoShape*, const GeoShape*> operands = getOps(booleanShape); + if (!operands.first || !operands.second){ + return {compressShift(booleanShape)}; + } + std::vector<const GeoShape*> components{}; + if (booleanShape->typeID() != GeoShapeSubtraction::getClassTypeID()) { + components = getBooleanComponents(operands.first); + std::vector<const GeoShape*> secCmp = getBooleanComponents(operands.second); + components.insert(components.end(), std::make_move_iterator(secCmp.begin()), + std::make_move_iterator(secCmp.end())); + } else { + if (operands.first->typeID() == GeoShapeSubtraction::getClassTypeID()) { + components = getBooleanComponents(operands.first); + } + components.push_back(compressShift(operands.second)); + } + return components; +} + + + +std::string printGeoShape(const GeoShape* shape) { + std::stringstream ostr{}; + constexpr double toDeg{1./GeoModelKernelUnits::deg}; + ostr<<shape->type()<<" ("<<shape<<") "; + const int typeID = shape->typeID(); + if (typeID == GeoShapeUnion::getClassTypeID()) { + const GeoShapeUnion* shapeUnion = dynamic_cast<const GeoShapeUnion*>(shape); + ostr<<"of {"<<printGeoShape(shapeUnion->getOpA())<<"} & {"<<printGeoShape(shapeUnion->getOpB())<<"}"; + } else if (typeID == GeoShapeSubtraction::getClassTypeID()) { + const GeoShapeSubtraction* subtractShape = dynamic_cast<const GeoShapeSubtraction*>(shape); + ostr<<"of {"<<printGeoShape(subtractShape->getOpB())<<"} from {"<<printGeoShape(subtractShape->getOpA())<<"}"; + } else if (typeID == GeoShapeIntersection::getClassTypeID()) { + const GeoShapeIntersection* intersectShape = dynamic_cast<const GeoShapeIntersection*>(shape); + ostr<<"between {"<<printGeoShape(intersectShape->getOpA())<<"} & {"<<printGeoShape(intersectShape->getOpB())<<"}"; + } else if (typeID == GeoShapeShift::getClassTypeID()) { + const GeoShapeShift* shiftShape = dynamic_cast<const GeoShapeShift*>(shape); + ostr<<"of "<<printGeoShape(shiftShape->getOp())<<" by "<<GeoTrf::toString(shiftShape->getX()); + } + /// Elementary shape types + else if (typeID == GeoBox::getClassTypeID()) { + const GeoBox* boxShape = dynamic_cast<const GeoBox*>(shape); + ostr<<" halfX="<<boxShape->getXHalfLength()<<", halfY="<<boxShape->getYHalfLength()<<", halfZ="<<boxShape->getZHalfLength(); + } else if (typeID == GeoTrd::getClassTypeID()) { + const GeoTrd* trd = dynamic_cast<const GeoTrd*>(shape); + ostr<<"halfX="<<trd->getXHalfLength1()<<"/"<<trd->getXHalfLength2()<<", "; + ostr<<"halfY="<<trd->getYHalfLength1()<<"/"<<trd->getYHalfLength2()<<", "; + ostr<<"halfZ="<<trd->getZHalfLength(); + } else if (typeID == GeoTube::getClassTypeID()) { + const GeoTube* tube = dynamic_cast<const GeoTube*>(shape); + ostr<<"rMin="<<tube->getRMin()<<", "; + ostr<<"rMax="<<tube->getRMax()<<", "; + ostr<<"halfZLength="<<tube->getZHalfLength(); + } else if (typeID == GeoTubs::getClassTypeID()) { + const GeoTubs* tube = dynamic_cast<const GeoTubs*>(shape); + ostr<<"rMin="<<tube->getRMin()<<", "; + ostr<<"rMax="<<tube->getRMax()<<", "; + ostr<<"start phi="<<tube->getSPhi()*toDeg<<", "; + ostr<<"dPhi="<<tube->getDPhi()*toDeg<<", "; + ostr<<"halfZ="<<tube->getZHalfLength(); + } else if (typeID == GeoCons::getClassTypeID()) { + const GeoCons* cons = dynamic_cast<const GeoCons*>(shape); + ostr<<"r1="<<cons->getRMin1()<<"/"<<cons->getRMax1()<<", "; + ostr<<"r2="<<cons->getRMin2()<<"/"<<cons->getRMax2()<<", "; + ostr<<"dZ="<<cons->getDZ()<<", "; + ostr<<"start phi="<<cons->getSPhi()*toDeg<<", "; + ostr<<"dPhi="<<cons->getDPhi()*toDeg; + } else if (typeID == GeoEllipticalTube::getClassTypeID()) { + const GeoEllipticalTube* tube = dynamic_cast<const GeoEllipticalTube*>(shape); + ostr<<"halfX="<<tube->getXHalfLength()<<", halfY="<<tube->getYHalfLength()<<", halfZ="<<tube->getZHalfLength(); + } else if (typeID == GeoPara::getClassTypeID()) { + const GeoPara* para = dynamic_cast<const GeoPara*>(shape); + ostr<<"halfX="<<para->getXHalfLength()<<", halfY="<<para->getYHalfLength()<<", halfZ="<<para->getZHalfLength(); + ostr<<"theta="<<para->getTheta()*toDeg<<", alpha="<<para->getAlpha()*toDeg<<", phi="<<para->getPhi()*toDeg; + } else if (typeID == GeoTorus::getClassTypeID()) { + const GeoTorus* torus = dynamic_cast<const GeoTorus*>(shape); + ostr<<"r="<<torus->getRMin()<<"/"<<torus->getRMax()<<", "; + ostr<<"Torus R="<<torus->getRTor()<<", "; + ostr<<"sPhi="<<torus->getSPhi()*toDeg<<", "; + ostr<<"dPhi="<<torus->getDPhi()*toDeg; + } + return ostr.str(); +} diff --git a/GeoModelCore/GeoModelFuncSnippets/src/StringUtils.cxx b/GeoModelCore/GeoModelFuncSnippets/src/StringUtils.cxx new file mode 100644 index 0000000000000000000000000000000000000000..c17fb500cdc2a0b85203ce32d64980eb9ce35c8c --- /dev/null +++ b/GeoModelCore/GeoModelFuncSnippets/src/StringUtils.cxx @@ -0,0 +1,139 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ +#include "GeoModelFuncSnippets/StringUtils.h" +#include "GeoModelFuncSnippets/throwExcept.h" +#include <limits> +#include <array> +#include <functional> +#include <iostream> +#include <sstream> +#include <charconv> +#include <algorithm> + +namespace GeoStrUtils { + + std::string whiteSpaces(const unsigned int n, const std::string_view space) { + return chainUp<std::string_view>(n , + [space](const unsigned int)->std::string_view{ return space; }, ""); + } + std::string replaceExpInString(std::string str, + const std::string_view exp, + const std::string_view rep) { + + std::size_t exPos = str.find(exp); + std::size_t expLen = exp.size(); + while(exPos != std::string::npos) { + str = str.substr(0, exPos) + std::string{rep} + str.substr(exPos + expLen, std::string::npos); + exPos = str.find(exp); + } + return str; + } + std::string_view longestCommonString(const std::string_view firstStr, + const std::string_view secondStr){ + if (firstStr.size() < secondStr.size()) return longestCommonString(secondStr, firstStr); + std::size_t commonPos{0}; + for ( ; commonPos <= secondStr.size(); ++commonPos) { + std::string_view sub_str = secondStr.substr(0, commonPos); + if (firstStr.find(sub_str) != 0) break; + } + return secondStr.substr(0, commonPos); + } + + + std::string resolveEnviromentVariables(const std::string_view inStr) { + std::string str{inStr}; + + while (str.find("${") != std::string::npos) { + std::string varName = str.substr(str.find("${") + 2, str.find("}") - str.find("${") - 2); + std::string envVar{std::getenv(varName.data()) ? std::getenv(varName.data()) : ""}; + str = replaceExpInString(str, str.substr(str.find("${"), str.find("}") - str.find("${") + 1), envVar); + } + return str; + } + + std::vector<std::string> tokenize(const std::string& str, + std::string_view delimiters) { + + std::vector<std::string> tokens{}; + // Skip delimiters at beginning. + std::string::size_type lastPos = str.find_first_not_of(delimiters, 0); + // Find first "non-delimiter". + std::string::size_type pos = str.find_first_of(delimiters, lastPos); + + while (std::string::npos != pos || std::string::npos != lastPos) { + // Found a token, add it to the vector. + tokens.push_back(str.substr(lastPos, pos - lastPos)); + // Skip delimiters. Note the "not_of" + lastPos = str.find_first_not_of(delimiters, pos); + // Find next "non-delimiter" + pos = str.find_first_of(delimiters, lastPos); + } + return tokens; + } + std::vector<double> tokenizeDouble(const std::string& the_str, + std::string_view delimiter){ + const std::vector<std::string> strTokens = tokenize(the_str, delimiter); + std::vector<double> toReturn{}; + std::transform(strTokens.begin(), strTokens.end(), std::back_inserter(toReturn), + [](const std::string& token){ + return atof(token); + }); + return toReturn; + } + std::string_view eraseWhiteSpaces(std::string_view str) { + if (str.empty()) return str; + size_t begin{0}, end{str.size() -1}; + while (std::isspace(str[begin])){ + ++begin; + } + while (end > 0 && std::isspace(str[end])){ + --end; + } + return str.substr(begin, end + 1); + } + std::vector<int> tokenizeInt(const std::string& the_str, + std::string_view delimiter) { + const std::vector<std::string> strTokens = tokenize(the_str, delimiter); + std::vector<int> toReturn{}; + std::transform(strTokens.begin(), strTokens.end(), std::back_inserter(toReturn), + [](const std::string& token){ + return atoi(token); + }); + return toReturn; + } + template <class dType> void convertToNumber(std::string_view str, dType& number) { + /// Allow for trailing & leading white spaces + if (str.empty()) { + number = 0; + return; + } + if (std::find_if(str.begin(), str.end(), [](const char c){ return std::isspace(c);}) != str.end()) { + std::string_view spaceFreeStr = eraseWhiteSpaces(str); + /// To avoid infinite recursion because of string like '42 24' check that white spaces have been indeed removed + if (spaceFreeStr.size() != str.size()) { + convertToNumber(spaceFreeStr, number); + return; + } + } + if (str[0]=='+') { + convertToNumber(str.substr(1), number); + return; + } + std::istringstream stream(std::string(str.data(), str.data()+str.size())); + stream >> number; + if (!stream) THROW_EXCEPTION("convertToNumber() - The string '"<<str<<"'. Contains unallowed chars"); + + } + int atoi(std::string_view str) { + int result{std::numeric_limits<int>::max()}; + convertToNumber(str, result); + return result; + } + + double atof(std::string_view str) { + double result{std::numeric_limits<double>::max()}; + convertToNumber(str, result); + return result; + } +} diff --git a/GeoModelCore/GeoModelFuncSnippets/src/TransformSorter.cxx b/GeoModelCore/GeoModelFuncSnippets/src/TransformSorter.cxx new file mode 100644 index 0000000000000000000000000000000000000000..8ad2d05cf6244292b16a9086e1f0626b98b54b77 --- /dev/null +++ b/GeoModelCore/GeoModelFuncSnippets/src/TransformSorter.cxx @@ -0,0 +1,46 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ +#include "GeoModelFuncSnippets/TransformSorter.h" +#include "GeoModelFuncSnippets/throwExcept.h" + +namespace GeoTrf { + bool TransformSorter::operator()(const std::unique_ptr<Transform3D>& a, + const std::unique_ptr<Transform3D>& b) const { + if (!a || !b) { + THROW_EXCEPTION("Nullptr given to comparator"); + } + return (*this)(*a, *b); + } + bool TransformSorter::operator()(const std::shared_ptr<Transform3D>& a, + const std::shared_ptr<Transform3D>& b) const { + if (!a || !b) { + THROW_EXCEPTION("Nullptr given to comparator"); + } + return (*this)(*a, *b); + } + bool TransformSorter::operator()(const Transform3D& a, const Transform3D& b) const { + return compare(a, b) < 0; + } + bool TransformSorter::operator()(const RotationMatrix3D&a, const RotationMatrix3D& b) const{ + return compare(a, b) < 0; + } + + int TransformSorter::compare(const Transform3D&a, const Transform3D& b) const{ + const Vector3D transA{a.translation()}, transB{b.translation()}; + const int transCmp = compare(transA, transB); + if (transCmp) return transCmp; + return compare(a.linear(), b.linear()); + } + int TransformSorter::compare(const RotationMatrix3D&a, const RotationMatrix3D& b) const{ + return getGeoRotationAngles(a).compare(getGeoRotationAngles(b)); + } + + bool TransformSorter::operator()(const ::GeoTransform* a, + const ::GeoTransform* b) const { + if (!a || !b) { + THROW_EXCEPTION("Nullptr given to comparator"); + } + return (*this)(a->getTransform(), b->getTransform()); + } +} \ No newline at end of file diff --git a/GeoModelCore/GeoModelFuncSnippets/src/TransformToStringConverter.cxx b/GeoModelCore/GeoModelFuncSnippets/src/TransformToStringConverter.cxx new file mode 100644 index 0000000000000000000000000000000000000000..cbf1150b7b7df66ec5b1ed1186398df9d0522f6b --- /dev/null +++ b/GeoModelCore/GeoModelFuncSnippets/src/TransformToStringConverter.cxx @@ -0,0 +1,59 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ +#include "GeoModelFuncSnippets/TransformToStringConverter.h" +#include "GeoModelKernel/Units.h" + +namespace{ + constexpr double toDeg = 1./ GeoModelKernelUnits::deg; +} + +namespace GeoTrf{ + std::string toString(const Transform3D& transform, bool useCoordAngles, int precision) { + std::stringstream ostr{}; + ostr << std::setiosflags(std::ios::fixed) << std::setprecision(precision); + const Vector3D trans = transform.translation(); + bool printed{false}; + if (std::sqrt(trans.dot(trans)) > 0.1 *GeoModelKernelUnits::micrometer) { + ostr<<"translation -- "; + ostr<<toString(trans, precision); + printed = true; + } + if (useCoordAngles) { + CoordEulerAngles angles = getCoordRotationAngles(transform); + if (angles) { + if (printed) ostr<<", "; + ostr<<"Euler angles -- "; + ostr<<toString(angles, precision); + printed = true; + } + } else { + EulerAngles angles = getGeoRotationAngles(transform); + if (angles){ + if(printed) ostr<<", "; + ostr<<"Euler angles -- "; + ostr<<toString(angles, precision); + printed = true; + } + } + + if (!printed) ostr<<"Identity transformation"; + return ostr.str(); + } + std::string toString(const EulerAngles& angles, int precision) { + std::stringstream ostr{}; + ostr << std::setiosflags(std::ios::fixed) << std::setprecision(precision); + ostr<<"phi: "<<angles.phi *toDeg<<", "; + ostr<<"theta: "<<angles.theta *toDeg<<", "; + ostr<<"psi: "<<angles.psi *toDeg; + return ostr.str(); + } + std::string toString(const CoordEulerAngles& angles, int precision) { + std::stringstream ostr{}; + ostr << std::setiosflags(std::ios::fixed) << std::setprecision(precision); + ostr <<"alpha: "<<angles.alpha * toDeg<<", "; + ostr <<"beta: "<<angles.beta * toDeg<<", "; + ostr <<"gamma: "<<angles.gamma * toDeg; + return ostr.str(); + } +} diff --git a/GeoModelCore/GeoModelFuncSnippets/src/defineWorld.cxx b/GeoModelCore/GeoModelFuncSnippets/src/defineWorld.cxx new file mode 100644 index 0000000000000000000000000000000000000000..e5185656f6f8364b770f7a39d7088a42675d00e8 --- /dev/null +++ b/GeoModelCore/GeoModelFuncSnippets/src/defineWorld.cxx @@ -0,0 +1,138 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ +#include "GeoModelFuncSnippets/defineWorld.h" +#include "GeoModelKernel/GeoElement.h" +#include "GeoModelKernel/GeoMaterial.h" +#include "GeoModelKernel/GeoBox.h" +#include "GeoModelKernel/GeoPhysVol.h" +#include "GeoModelKernel/GeoFullPhysVol.h" +#include "GeoModelKernel/GeoVolumeCursor.h" +#include "GeoModelKernel/GeoAlignableTransform.h" +#include "GeoModelKernel/Units.h" + +GeoIntrusivePtr<GeoPhysVol> createGeoWorld(const double worldBoxX, + const double worldBoxY, + const double worldBoxZ) { + + + constexpr double gr = GeoModelKernelUnits::gram; + constexpr double mole = GeoModelKernelUnits::mole; + constexpr double cm3 = GeoModelKernelUnits::cm3; + + // Define the chemical elements + GeoIntrusivePtr<GeoElement> Nitrogen{new GeoElement ("Nitrogen" ,"N" , 7.0 , 14.0031 *gr/mole)}; + GeoIntrusivePtr<GeoElement> Oxygen{new GeoElement ("Oxygen" ,"O" , 8.0 , 15.9949 *gr/mole)}; + GeoIntrusivePtr<GeoElement> Argon{new GeoElement ("Argon" ,"Ar" , 18.0 , 39.9624 *gr/mole)}; + GeoIntrusivePtr<GeoElement> Hydrogen{new GeoElement ("Hydrogen" ,"H" , 1.0 , 1.00782503081372 *gr/mole)}; + + constexpr double densityOfAir=0.001290 *gr/cm3; + GeoIntrusivePtr<GeoMaterial> air{new GeoMaterial("GeoModelAir", densityOfAir)}; + air->add(Nitrogen , 0.7494); + air->add(Oxygen, 0.2369); + air->add(Argon, 0.0129); + air->add(Hydrogen, 0.0008); + air->lock(); + + + GeoIntrusivePtr<GeoBox> worldBox{new GeoBox(worldBoxX, worldBoxY, worldBoxZ)}; + GeoIntrusivePtr<GeoLogVol> worldLog{new GeoLogVol("WorldLog", worldBox, air)}; + GeoIntrusivePtr<GeoPhysVol> world{new GeoPhysVol(worldLog)}; + + return world; +} + +GeoIntrusivePtr<GeoPhysVol> resizeGeoWorld(GeoIntrusivePtr<GeoPhysVol> world) +{ + if (world) + { + //resize the world volume to the real needed volume + + // get number of children volumes + unsigned int nChild=world->getNChildVols(); + + //Dimensions of the bounding boxes + double xmin=0.,ymin=0.,zmin=0.,xmax=0.,ymax=0.,zmax=0.; + double xworld=0.,yworld=0.,zworld=0.; + + // loop over all children volumes + for (unsigned int i=0; i<nChild; i++) + { + PVConstLink nodeLink = world->getChildVol(i); + if ( dynamic_cast<const GeoVPhysVol*>( &(*( nodeLink ))) ) + { + const GeoVPhysVol *childVolV = &(*( nodeLink )); + + if ( dynamic_cast<const GeoPhysVol*>(childVolV) ) { + const GeoPhysVol* childVol = dynamic_cast<const GeoPhysVol*>(childVolV); + childVol->getLogVol()->getShape()->extent(xmin, ymin, zmin, xmax, ymax, zmax); + } + else if ( dynamic_cast<const GeoFullPhysVol*>(childVolV) ) { + const GeoFullPhysVol* childVol = dynamic_cast<const GeoFullPhysVol*>(childVolV); + childVol->getLogVol()->getShape()->extent(xmin, ymin, zmin, xmax, ymax, zmax); + + } + xworld=std::max({xworld,std::abs(xmin),std::abs(xmax)}); + yworld=std::max({yworld,std::abs(ymin),std::abs(ymax)}); + zworld=std::max({zworld,std::abs(zmin),std::abs(zmax)}); + } + } + + GeoIntrusivePtr<GeoPhysVol> resizedWorld{createGeoWorld(xworld, yworld, zworld)}; + + for (unsigned int i=0; i< world->getNChildNodes(); i++){ + const GeoGraphNode * node = *(world->getChildNode(i)); + + + if (dynamic_cast<const GeoVPhysVol*>( node )) + { + if ( dynamic_cast<const GeoFullPhysVol*>(node) ){ + const GeoFullPhysVol* nodeFullPhysVol = dynamic_cast<const GeoFullPhysVol*>(node); + resizedWorld->add((GeoGraphNode *)nodeFullPhysVol); + + } + else if ( dynamic_cast<const GeoPhysVol*>(node) ){ + const GeoPhysVol* nodePhysVol = dynamic_cast<const GeoPhysVol*>(node); + resizedWorld->add((GeoGraphNode *)nodePhysVol); + + } + } + else if (dynamic_cast<const GeoNameTag*>( node )){ + const GeoNameTag* nodeTag = dynamic_cast<const GeoNameTag*>(node); + resizedWorld->add((GeoGraphNode *)nodeTag); + + } + + else if (dynamic_cast<const GeoAlignableTransform*>( node )){ + const GeoAlignableTransform* nodeAT = dynamic_cast<const GeoAlignableTransform*>(node); + resizedWorld->add((GeoGraphNode *)nodeAT); + + } + + else if (dynamic_cast<const GeoSerialTransformer*>( node )){ + const GeoSerialTransformer* nodeST = dynamic_cast<const GeoSerialTransformer*>(node); + resizedWorld->add((GeoGraphNode *)nodeST); + + } + + else if (dynamic_cast<const GeoSerialDenominator*>( node )){ + const GeoSerialDenominator* nodeSD = dynamic_cast<const GeoSerialDenominator*>(node); + resizedWorld->add((GeoGraphNode *)nodeSD); + + } + else if (dynamic_cast<const GeoTransform*>( node )){ + const GeoTransform* nodeTransform = dynamic_cast<const GeoTransform*>(node); + resizedWorld->add((GeoGraphNode *)nodeTransform); + + }else if (dynamic_cast<const GeoIdentifierTag*>( node )){ + const GeoIdentifierTag* nodeIT = dynamic_cast<const GeoIdentifierTag*>(node); + resizedWorld->add((GeoGraphNode *)nodeIT); + + } + } + + return resizedWorld; + + } + return world; +} diff --git a/GeoModelCore/GeoModelFuncSnippets/src/getChildNodesWithTrf.cxx b/GeoModelCore/GeoModelFuncSnippets/src/getChildNodesWithTrf.cxx new file mode 100644 index 0000000000000000000000000000000000000000..462ac8b684cd10e4a30b1ea00d5f4009d9100c59 --- /dev/null +++ b/GeoModelCore/GeoModelFuncSnippets/src/getChildNodesWithTrf.cxx @@ -0,0 +1,66 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ +#include "GeoModelFuncSnippets/getChildNodesWithTrf.h" + +#include "GeoModelFuncSnippets/GeoPhysVolSorter.h" +#include "GeoModelFuncSnippets/TransformSorter.h" +#include "GeoModelKernel/GeoVolumeCursor.h" +#include "GeoModelKernel/GeoFullPhysVol.h" + +namespace { + constexpr std::string_view dummyNodeName{"ANON"}; +} + + + GeoChildNodeWithTrf::GeoChildNodeWithTrf(GeoVolumeCursor& curs): + transform{curs.getTransform()}, + volume{curs.getVolume()}, + nodeName{curs.getName()}, + isAlignable{curs.hasAlignableTransform()}, + isSensitive{typeid(*volume) == typeid(GeoFullPhysVol)} { + //// Do not specify a node name if it's a dummy one + if (nodeName == dummyNodeName) { + nodeName = volume->getLogVol()->getName(); + + } +} + +std::vector <GeoChildNodeWithTrf> getChildrenWithRef(PVConstLink& physVol, + bool summarizeEqualVol) { + std::vector<GeoChildNodeWithTrf> children{}; + + static const GeoPhysVolSorter physVolSort{}; + static const GeoTrf::TransformSorter transSort{}; + + + GeoVolumeCursor cursor{physVol}; + GeoTrf::Transform3D lastNodeTrf{GeoTrf::Transform3D::Identity()}; + + while (!cursor.atEnd()) { + if (children.empty() || !summarizeEqualVol) { + children.emplace_back(cursor); + cursor.next(); + continue; + } + GeoChildNodeWithTrf& prevChild{children.back()}; + GeoChildNodeWithTrf currentChild{cursor}; + if (prevChild.isAlignable != currentChild.isAlignable || + prevChild.isSensitive != currentChild.isSensitive || + physVolSort.compare(prevChild.volume, currentChild.volume)) { + children.emplace_back(std::move(currentChild)); + } else if (prevChild.nCopies == 1) { + ++prevChild.nCopies; + prevChild.inductionRule = prevChild.transform.inverse() * + currentChild.transform; + } else if (!transSort.compare(prevChild.inductionRule, + lastNodeTrf.inverse() * currentChild.transform)) { + ++prevChild.nCopies; + } else { + children.emplace_back(std::move(currentChild)); + } + lastNodeTrf = cursor.getTransform(); + cursor.next(); + } + return children; +} diff --git a/GeoModelCore/GeoModelFuncSnippets/tests/testGeoShapeSet.cxx b/GeoModelCore/GeoModelFuncSnippets/tests/testGeoShapeSet.cxx new file mode 100644 index 0000000000000000000000000000000000000000..b992be28432add14b12f0762dbf76e25406395f1 --- /dev/null +++ b/GeoModelCore/GeoModelFuncSnippets/tests/testGeoShapeSet.cxx @@ -0,0 +1,105 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ +#include "GeoModelKernel/Units.h" +#include "GeoModelKernel/GeoDefinitions.h" +#include "GeoModelFuncSnippets/GeoShapeSorter.h" +#include "GeoModelFuncSnippets/GeoShapeUtils.h" + +#include "GeoModelKernel/GeoBox.h" +#include "GeoModelKernel/GeoTube.h" +#include "GeoModelKernel/GeoShapeShift.h" + + +#include <stdlib.h> +#include <iostream> + +template<class T, typename... args> bool insertVolume(const bool printFailure, + GeoShapeSet<GeoShape>& set, + args... a) { + GeoIntrusivePtr<T> newPtr{new T(a...)}; + + const auto insert_itr = set.insert(newPtr); + if (insert_itr.second && newPtr->refCount() == 2) return true; + if (printFailure) { + std::cerr<<"Shape insertion failed "<<printGeoShape(newPtr)<<std::endl; + std::cerr<<"Shape "<<printGeoShape(*insert_itr.first)<<" is taking its place "<<std::endl; + } + return false; +} + +int main() { + GeoShapeSet<GeoShape> shapeColl{}; + GeoShapeSorter shapeSorter{}; + + if (!insertVolume<GeoBox>(true, shapeColl, 10.,10.,10.)) { + std::cerr<<"testGeoShapeSorter() "<<__LINE__<<" test failed. "<<std::endl; + return EXIT_FAILURE; + } + if (insertVolume<GeoBox>(false, shapeColl, 10.,10.,10.)) { + std::cerr<<"testGeoShapeSorter() "<<__LINE__<<" GeoBox A has been inserted twice. "<<std::endl; + return EXIT_FAILURE; + } + if (!insertVolume<GeoBox>(true, shapeColl, 11.,10., 10.)) { + std::cerr<<"testGeoShapeSorter() "<<__LINE__<<" test failed. "<<std::endl; + return EXIT_FAILURE; + } + if (!insertVolume<GeoBox>(true, shapeColl, 10., 11., 10.)) { + std::cerr<<"testGeoShapeSorter() "<<__LINE__<<" test failed. "<<std::endl; + return EXIT_FAILURE; + } + + if (!insertVolume<GeoBox>(true, shapeColl, 10., 10., 11.)) { + std::cerr<<"testGeoShapeSorter() "<<__LINE__<<" test failed. "<<std::endl; + return EXIT_FAILURE; + } + + if (!insertVolume<GeoBox>(true, shapeColl, 10., 11., 11.)) { + std::cerr<<"testGeoShapeSorter() "<<__LINE__<<" test failed. "<<std::endl; + return EXIT_FAILURE; + } + ///############################################################## + /// GeoTube + ///############################################################## + if (!insertVolume<GeoTube>(true, shapeColl, 10.,10.,10.)) { + std::cerr<<"testGeoShapeSorter() "<<__LINE__<<" test failed. "<<std::endl; + return EXIT_FAILURE; + } + if (insertVolume<GeoTube>(false, shapeColl, 10.,10.,10.)) { + std::cerr<<"testGeoShapeSorter() "<<__LINE__<<" GeoTube A has been inserted twice. "<<std::endl; + return EXIT_FAILURE; + } + if (!insertVolume<GeoTube>(true, shapeColl, 11.,10., 10.)) { + std::cerr<<"testGeoShapeSorter() "<<__LINE__<<" test failed. "<<std::endl; + return EXIT_FAILURE; + } + if (!insertVolume<GeoTube>(true, shapeColl, 10., 11., 10.)) { + std::cerr<<"testGeoShapeSorter() "<<__LINE__<<" test failed. "<<std::endl; + return EXIT_FAILURE; + } + + if (!insertVolume<GeoTube>(true, shapeColl, 10., 10., 11.)) { + std::cerr<<"testGeoShapeSorter() "<<__LINE__<<" test failed. "<<std::endl; + return EXIT_FAILURE; + } + + if (!insertVolume<GeoTube>(true, shapeColl, 10., 11., 11.)) { + std::cerr<<"testGeoShapeSorter() "<<__LINE__<<" test failed. "<<std::endl; + return EXIT_FAILURE; + } + + { + GeoIntrusivePtr<GeoTube> tubeShift{new GeoTube(2,3,4)}; + GeoTrf::Transform3D trans1{GeoTrf::GeoTransformRT{GeoTrf::GeoRotation(0., 2., 2.), GeoTrf::Vector3D{1.,0.,3}}}; + GeoTrf::Transform3D trans2{GeoTrf::GeoTransformRT{GeoTrf::GeoRotation(2.,0., 2.), GeoTrf::Vector3D{2.,0.,3}}}; + if (!insertVolume<GeoShapeShift>(true, shapeColl, tubeShift, trans1)){ + std::cerr<<"testGeoShapeSorter() "<<__LINE__<<" test failed. "<<std::endl; + return EXIT_FAILURE; + } + if (!insertVolume<GeoShapeShift>(true, shapeColl, tubeShift, trans2)){ + std::cerr<<"testGeoShapeSorter() "<<__LINE__<<" test failed. "<<std::endl; + return EXIT_FAILURE; + } + } + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/GeoModelCore/GeoModelFuncSnippets/tests/testStringUtils.cxx b/GeoModelCore/GeoModelFuncSnippets/tests/testStringUtils.cxx new file mode 100644 index 0000000000000000000000000000000000000000..c21262be73bb4f01f4e606f3860dec4f7146055c --- /dev/null +++ b/GeoModelCore/GeoModelFuncSnippets/tests/testStringUtils.cxx @@ -0,0 +1,29 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ + +#include "GeoModelFuncSnippets/StringUtils.h" +#include "GeoModelFuncSnippets/throwExcept.h" +#include <iostream> +#include <stdlib.h> +using namespace GeoStrUtils; + +namespace { + std::string getEnvVar(const std::string& varName){ + return std::getenv(varName.c_str()) ? std::string{std::getenv(varName.c_str())} : std::string{}; + } +} + +int main() { + if (resolveEnviromentVariables("${PWD}") != getEnvVar("PWD")) { + THROW_EXCEPTION("PWD has been resolved differently "<<resolveEnviromentVariables("${PWD}") + <<" vs. "<<getEnvVar("PWD")); + } + + if (resolveEnviromentVariables("${PWD}/Kuchen") != getEnvVar("PWD")+"/Kuchen") { + THROW_EXCEPTION("PWD/Kuchen has been resolved differently "<<resolveEnviromentVariables("${PWD}/Kuchen") + <<" vs. "<<getEnvVar("PWD")<<"/Kuchen"); + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/GeoModelCore/GeoModelFuncSnippets/tests/testTransformSorter.cxx b/GeoModelCore/GeoModelFuncSnippets/tests/testTransformSorter.cxx new file mode 100644 index 0000000000000000000000000000000000000000..9889827c866c100495e6a1a278d155f85910d92f --- /dev/null +++ b/GeoModelCore/GeoModelFuncSnippets/tests/testTransformSorter.cxx @@ -0,0 +1,61 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ + +#include "GeoModelFuncSnippets/TransformSorter.h" +#include "GeoModelFuncSnippets/TransformToStringConverter.h" +#include "GeoModelKernel/Units.h" +#include <stdlib.h> +#include <iostream> + +std::ostream& operator<<(std::ostream& ostr, const GeoTrf::Transform3D& trans) { + ostr<<GeoTrf::toString(trans, true, 2); + return ostr; +} + +#define TEST_TRANSFORM(TRANS) \ + std::cout<<"testTransformSorter() "<<__LINE__<<" Test transformation "<<TRANS<<std::endl; \ + if (sorter(TRANS, TRANS)) { \ + std::cerr<<"testTransformSorter() "<<__LINE__<<" transformation "<<TRANS<<" is less than itself "<<std::endl; \ + return EXIT_FAILURE; \ + } +#define COMPARE_SORTER(TRANSA, TRANSB) \ + if (sorter(TRANSA, TRANSB) == sorter(TRANSB, TRANSA)) { \ + std::cerr<<"testTransformSorter() "<<__LINE__<<" transformations " \ + <<TRANSA<<" & "<<TRANSB<<" are identical. "<<std::endl; \ + const GeoTrf::Vector3D vecA{TRANSA.translation()}, vecB{TRANSB.translation()}; \ + std::cerr<<"testTransformSorter() comparison result (A,B): "<<sorter(TRANSA, TRANSB) \ + << " compare result: "<<sorter.compare(TRANSA, TRANSB) \ + << " -- linear part: "<<sorter(TRANSA.linear(), TRANSB.linear()) << " / " \ + << sorter.compare(TRANSA.linear(), TRANSB.linear()) \ + << " -- translation part: "<<sorter(vecA, vecB) \ + << " / "<<sorter.compare(vecA, vecB)<<std::endl; \ + std::cerr<<"testTransformSorter() comparison result (B,A): "<<sorter(TRANSB, TRANSA) \ + << " compare result: "<<sorter.compare(TRANSB, TRANSA) \ + << " -- linear part: "<<sorter(TRANSB.linear(), TRANSA.linear()) << " / " \ + << sorter.compare(TRANSB.linear(), TRANSA.linear()) \ + << " -- translation part: "<<sorter(vecB, vecA) \ + << " / "<<sorter.compare(vecB, vecA)<<std::endl; \ + return EXIT_FAILURE; \ + } +int main() { + constexpr double deg = GeoModelKernelUnits::deg; + GeoTrf::TransformSorter sorter{}; + GeoTrf::CoordEulerAngles anglesA{45.*deg, 0., 0.}; + GeoTrf::Transform3D transA{GeoTrf::GeoTransformRT{GeoTrf::GeoRotation{anglesA}, 10. *GeoTrf::Vector3D::UnitX()}}; + TEST_TRANSFORM(transA); + + GeoTrf::CoordEulerAngles anglesB{0.,0.,0.}; + GeoTrf::Transform3D transB{GeoTrf::GeoTransformRT{GeoTrf::GeoRotation{anglesB}, 10. *GeoTrf::Vector3D::UnitX()}}; + TEST_TRANSFORM(transB); + + COMPARE_SORTER(transA, transB); + + + GeoTrf::Transform3D transC{GeoTrf::Translate3D{1, -1, 0.}}; + TEST_TRANSFORM(transC) + COMPARE_SORTER(transA, transC); + COMPARE_SORTER(transB, transC); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/GeoModelCore/GeoModelKernel/CMakeLists.txt b/GeoModelCore/GeoModelKernel/CMakeLists.txt index 5f01934699c73582b9fd4178f0a3c988b225ff65..819c6c9521ce5d44334faedad600506537153082 100644 --- a/GeoModelCore/GeoModelKernel/CMakeLists.txt +++ b/GeoModelCore/GeoModelKernel/CMakeLists.txt @@ -13,9 +13,6 @@ target_include_directories( GeoModelKernel PUBLIC $<INSTALL_INTERFACE:include> ) source_group( "GeoModelKernel" FILES ${HEADERS} ) source_group( "src" FILES ${SOURCES} ) -if( GEOMODEL_USE_BUILTIN_EIGEN3 ) - add_dependencies( GeoModelKernel Eigen3 ) -endif() set_target_properties( GeoModelKernel PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR} ) @@ -48,3 +45,21 @@ install(TARGETS GeoModelKernel install( FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/GeoModelKernel COMPONENT Development ) + + + file(GLOB_RECURSE files "tests/*.cxx") +foreach(_exeFile ${files}) + get_filename_component(_theExec ${_exeFile} NAME_WE) + get_filename_component(_theLoc ${_exeFile} DIRECTORY) + + if(${_theLoc} MATCHES "DoNotBuild") + continue() + endif() + + add_executable(${_theExec} ${_exeFile}) + target_link_libraries( ${_theExec} GeoModelKernel) + add_test(NAME ${_theExec} + COMMAND ${_theExec}) + +endforeach() + diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/ConstLink.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/ConstLink.h deleted file mode 100644 index 42c097699de07d60bc5155911bcfdd79b2cbb7f3..0000000000000000000000000000000000000000 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/ConstLink.h +++ /dev/null @@ -1,205 +0,0 @@ -/* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -*/ - -#ifndef GEOMODELKERNEL_CONSTLINK_H -#define GEOMODELKERNEL_CONSTLINK_H - -/** - * @class ConstLink - * - * @brief Smart links to reference-counted pointers. Used in this - * package for calorimeter cells - ** Template Smart Pointer Class. This reference counted - * link allocates on demand. It audits the total pointer - * count and collects the garbage when nobody's looking. - */ - -template <class T> -class ConstLink -{ - public: - - - /** - * @brief Constructor - */ - ConstLink(); - - /** - * @brief Copy Constructor - */ - ConstLink(const ConstLink< T > &right); - - /** - * @brief Constructor - */ - ConstLink (const T *target); - - /** - * @brief Destructor - */ - virtual ~ConstLink(); - - /** - * @brief Assignment - */ - ConstLink< T > & operator=(const ConstLink< T > &right); - - /** - * @brief Equality - */ - int operator==(const ConstLink< T > &right) const; - - /** - * @brief Inequality - */ - int operator!=(const ConstLink< T > &right) const; - - - /** - * @brief Relational operator - */ - int operator<(const ConstLink< T > &right) const; - - /** - * @brief Relational operator - */ - int operator>(const ConstLink< T > &right) const; - - /** - * @brief Relational operator - */ - int operator<=(const ConstLink< T > &right) const; - - /** - * @brief Relational operator - */ - int operator>=(const ConstLink< T > &right) const; - - - - /** - * @brief Dereference: (*t).method(); - */ - virtual const T & operator * () const; - - /** - * @brief Dereference: t->method() - */ - virtual const T * operator -> () const; - - /** - * @brief Check pointer validity: if (t) {...} - */ - operator bool () const; - - - - private: - /** - * @brief Raw pointer to reference counted object. - */ - mutable T *m_ptr; -}; - - - -template <class T> -inline ConstLink<T>::ConstLink() - :m_ptr(nullptr) -{ -} - -template <class T> -inline ConstLink<T>::ConstLink(const ConstLink<T> &right) - :m_ptr(right.m_ptr) -{ - if (m_ptr) m_ptr->ref(); -} - -template <class T> -inline ConstLink<T>::ConstLink (const T *target) - :m_ptr(const_cast<T *> (target)) -{ - if (target) target->ref(); -} - - -template <class T> -inline ConstLink<T>::~ConstLink() -{ - if (m_ptr) m_ptr->unref(); -} - - -template <class T> -inline ConstLink<T> & ConstLink<T>::operator=(const ConstLink<T> &right) -{ - if (this!=&right) { - if (m_ptr) m_ptr->unref(); - m_ptr = right.m_ptr; - if (m_ptr) m_ptr->ref(); - } - return *this; -} - - -template <class T> -inline int ConstLink<T>::operator==(const ConstLink<T> &right) const -{ - return m_ptr==right.m_ptr; -} - -template <class T> -inline int ConstLink<T>::operator!=(const ConstLink<T> &right) const -{ - return m_ptr!=right.m_ptr; -} - - -template <class T> -inline int ConstLink<T>::operator<(const ConstLink<T> &right) const -{ - return m_ptr<right.m_ptr; -} - -template <class T> -inline int ConstLink<T>::operator>(const ConstLink<T> &right) const -{ - return m_ptr>right.m_ptr; -} - -template <class T> -inline int ConstLink<T>::operator<=(const ConstLink<T> &right) const -{ - return m_ptr<=right.m_ptr; -} - -template <class T> -inline int ConstLink<T>::operator>=(const ConstLink<T> &right) const -{ - return m_ptr>=right.m_ptr; -} - - - -template <class T> -inline const T & ConstLink<T>::operator * () const -{ - return *m_ptr; -} - -template <class T> -inline const T * ConstLink<T>::operator -> () const -{ - return m_ptr; -} - -template <class T> -inline ConstLink<T>::operator bool () const -{ - return m_ptr; -} - -#endif diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoAbsPositionInfo.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoAbsPositionInfo.h index d6b164032682743fbe8c966ffb34f5ed6badd87c..c8f8c8c68a2b773ad941aacb563426b5d608d09e 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoAbsPositionInfo.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoAbsPositionInfo.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #ifndef GEOMODELKERNEL_GEOABSPOSITIONINFO_H @@ -13,18 +13,23 @@ */ #include <GeoModelKernel/GeoDefinitions.h> +#include <memory> class GeoAbsPositionInfo { public: - GeoAbsPositionInfo(); - ~GeoAbsPositionInfo(); + GeoAbsPositionInfo() = default; + ~GeoAbsPositionInfo() = default; // Returns the default absolute transform. - const GeoTrf::Transform3D * getAbsTransform () const; + const GeoTrf::Transform3D * getAbsTransform () const { + return m_absTransform.get(); + } // Returns the default absolute transform. - const GeoTrf::Transform3D * getDefAbsTransform () const; + const GeoTrf::Transform3D * getDefAbsTransform () const { + return m_defAbsTransform.get(); + } // Clears the absolute transform. @@ -40,26 +45,14 @@ class GeoAbsPositionInfo void setDefAbsTransform (const GeoTrf::Transform3D & xform); private: - GeoAbsPositionInfo(const GeoAbsPositionInfo &right); - GeoAbsPositionInfo & operator=(const GeoAbsPositionInfo &right); // The absolute transform from the world coord down to this // positioned object. - GeoTrf::Transform3D *m_absTransform; + std::unique_ptr<GeoTrf::Transform3D> m_absTransform{}; // The default absolute transform from the world coord down // to this positioned object. - GeoTrf::Transform3D *m_defAbsTransform; + std::unique_ptr<GeoTrf::Transform3D> m_defAbsTransform{}; }; -inline const GeoTrf::Transform3D * GeoAbsPositionInfo::getAbsTransform () const -{ - return m_absTransform; -} - -inline const GeoTrf::Transform3D * GeoAbsPositionInfo::getDefAbsTransform () const -{ - return m_defAbsTransform; -} - #endif diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoAccessVolAndSTAction.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoAccessVolAndSTAction.h index e917598faaa157d882eaf07585867b563a130123..da372256e53b7fbe1d5bcf9494a35010fd53eab6 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoAccessVolAndSTAction.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoAccessVolAndSTAction.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #ifndef GEOMODELKERNEL_GEOACCESSVOLANDSTACTION_H @@ -21,11 +21,10 @@ class GeoVPhysVol; class GeoTransform; -class GeoAccessVolAndSTAction final : public GeoNodeAction -{ +class GeoAccessVolAndSTAction final : public GeoNodeAction { public: GeoAccessVolAndSTAction(unsigned int index); - virtual ~GeoAccessVolAndSTAction() override; + virtual ~GeoAccessVolAndSTAction() = default; virtual void handleTransform(const GeoTransform* xform) override; virtual void handlePhysVol(const GeoPhysVol* vol) override; @@ -51,17 +50,17 @@ class GeoAccessVolAndSTAction final : public GeoNodeAction const GeoAccessVolAndSTAction & operator=(const GeoAccessVolAndSTAction &right); /// A pointer to the ith physical volume under this one. - PVConstLink m_volume; + PVConstLink m_volume{}; /// A pointer to the Serial Transformer - const GeoSerialTransformer* m_serialTransformer; + const GeoSerialTransformer* m_serialTransformer{nullptr}; /// The transformation and default transformation to the ith volume. - GeoTrf::Transform3D m_transform; - GeoTrf::Transform3D m_defTransform; + GeoTrf::Transform3D m_transform{GeoTrf::Transform3D::Identity()}; + GeoTrf::Transform3D m_defTransform{GeoTrf::Transform3D::Identity()}; - unsigned int m_index; - unsigned int m_counter; + unsigned int m_index{0}; + unsigned int m_counter{0}; /// The name of the volume. From a nametag or a serial denominator mutable std::string m_name; @@ -70,12 +69,12 @@ class GeoAccessVolAndSTAction final : public GeoNodeAction mutable Query<unsigned int> m_id; /// A pointer to a name tag. If the volume is named. - const GeoNameTag *m_nameTag; - const GeoSerialDenominator *m_serialDenominator; - const GeoIdentifierTag *m_idTag; + const GeoNameTag *m_nameTag{nullptr}; + const GeoSerialDenominator *m_serialDenominator{nullptr}; + const GeoIdentifierTag *m_idTag{nullptr}; std::vector<const GeoTransform *> m_pendingTransformList; - unsigned int m_serialDenomPosition; + unsigned int m_serialDenomPosition{0}; }; #endif diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoAlignableTransform.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoAlignableTransform.h index 3af0c03752dbdce76a62b1778177c19841bb4436..b7c85ebc50eb8a5c3ba5748536ab3a21638e6be2 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoAlignableTransform.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoAlignableTransform.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #ifndef GEOMODELKERNEL_GEOALIGNABLETRANSFORM_H @@ -7,6 +7,7 @@ #include "GeoModelKernel/GeoTransform.h" #include <vector> +#include <memory> #include <mutex> class GeoVAlignmentStore; @@ -35,16 +36,14 @@ class GeoAlignableTransform final : public GeoTransform virtual void dockTo(GeoVPhysVol* parent) override; protected: - virtual ~GeoAlignableTransform() override; + virtual ~GeoAlignableTransform() = default; private: - GeoAlignableTransform(const GeoAlignableTransform &right); - GeoAlignableTransform & operator=(const GeoAlignableTransform &right); // Pointer to an alignment correction. Until some // alignment correction is set, this pointer is nullptr and // the memory is unallocated. - GeoTrf::Transform3D* m_delta; + std::unique_ptr<GeoTrf::Transform3D> m_delta{}; // We need to protext m_delta with a mutex in order to avoid // memory corruption in multithreaded applications diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoBox.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoBox.h index b024be9ad71ee38aade79b6114fda765cc655bfb..3542adc221cea86cfb8b9648a584b13c22b2b431 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoBox.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoBox.h @@ -10,73 +10,67 @@ class GeoBox : public GeoShape { public: - // Constructor for the BOX. + // Constructor for the BOX GeoBox (double XHalfLength, double YHalfLength, double ZHalfLength); - // Returns the volume of the shape, for mass inventory + // Returns the volume of the shape, for mass inventory virtual double volume () const; - // Returns the BOX shape type, as a string. - virtual const std::string & type () const; + // Returns the bonding box of the shape + virtual void extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const; - // Returns the BOX shape type, as a coded integer. - virtual ShapeType typeID () const; + // Returns true if the shape contains the point, false otherwise. + virtual bool contains (double x, double y, double z) const; - // Executes a GeoShapeAction. + // Returns the BOX shape type, as a string + virtual const std::string & type () const { + return getClassType(); + } + + // Returns the BOX shape type, as a coded integer + virtual ShapeType typeID() const { + return getClassTypeID(); + } + + // Executes a GeoShapeAction virtual void exec (GeoShapeAction *action) const; - // For type identification. - static const std::string& getClassType (); + // For type identification + static const std::string& getClassType () { + return s_classType; + } - // For type identification., - static ShapeType getClassTypeID (); + // For type identification + static ShapeType getClassTypeID () { + return s_classTypeID; + } - // Half length in the x-direction. - const double& getXHalfLength () const; + // Half length in the x-direction + double getXHalfLength () const { + return m_xHalfLength; + } - // Half-length in the y direction. - const double& getYHalfLength () const; + // Half-length in the y direction + double getYHalfLength () const { + return m_yHalfLength; + } - // Half-length in the z direction. - const double& getZHalfLength () const; + // Half-length in the z direction + double getZHalfLength () const { + return m_zHalfLength; + } - protected: - virtual ~GeoBox(); - private: - GeoBox(const GeoBox &right); - GeoBox & operator=(const GeoBox &right); + protected: + virtual ~GeoBox() = default; static const std::string s_classType; static const ShapeType s_classTypeID; - double m_xHalfLength; - double m_yHalfLength; - double m_zHalfLength; + double m_xHalfLength{0.}; + double m_yHalfLength{0.}; + double m_zHalfLength{0.}; }; -inline const std::string& GeoBox::getClassType () -{ - return s_classType; -} - -inline ShapeType GeoBox::getClassTypeID () -{ - return s_classTypeID; -} - -inline const double& GeoBox::getXHalfLength () const -{ - return m_xHalfLength; -} - -inline const double& GeoBox::getYHalfLength () const -{ - return m_yHalfLength; -} - -inline const double& GeoBox::getZHalfLength () const -{ - return m_zHalfLength; -} #endif diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoCons.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoCons.h index 052e59d381bf07a077d7b70dc0580a4aeed28510..b7fbf473caa3a3bb585142da5acf3b9efbb8e2be 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoCons.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoCons.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #ifndef GEOMODELKERNEL_GEOCONS_H @@ -7,112 +7,75 @@ #include "GeoModelKernel/GeoShape.h" -class GeoCons : public GeoShape -{ +class GeoCons : public GeoShape { public: GeoCons (double RMin1, double RMin2, double RMax1, double RMax2, double DZ, double SPhi, double DPhi); - // Returns the volume of the shape, for mass inventory + // Returns the volume of the shape, for mass inventory. virtual double volume () const; - // Returns the CONS shape type, as a string. - virtual const std::string & type () const; - - // Returns the CONS shape type, as a coded integer. - virtual ShapeType typeID () const; - - // Executes a GeoShapeAction + // Returns the bonding box of the shape. + virtual void extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const; + + // Returns true if the shape contains the point, false otherwise. + virtual bool contains (double x, double y, double z) const; + + // Returns the CONS shape type, as a string. + virtual const std::string & type () const { + return getClassType(); + } + + // Returns the CONS shape type, as a coded integer. + virtual ShapeType typeID () const { + return getClassTypeID(); + } + + // Executes a GeoShapeAction. virtual void exec (GeoShapeAction *action) const; - - // For type identification. - static const std::string& getClassType (); - - // For type identification. - static ShapeType getClassTypeID (); - - // Inside radius at -dZ - const double& getRMin1 () const; - - // Inside radius at +dZ - const double& getRMin2 () const; - - // Outside radius at -dZ - const double& getRMax1 () const; - - // Outside radius at +dZ - const double& getRMax2 () const; - - // Half length in Z direction. - const double& getDZ () const; - - // Starting angle of the segment in radians - const double& getSPhi () const; - - // Delta angle of the segment in radians. - const double& getDPhi () const; - - protected: - virtual ~GeoCons(); - + + // For type identification. + static const std::string& getClassType () { + return s_classType; + } + + // For type identification. + static ShapeType getClassTypeID() { + return s_classTypeID; + } + + // Inside radius at -dZ + double getRMin1 () const { return m_rMin1; } + // Inside radius at +dZ + double getRMin2 () const { return m_rMin2; } + // Outside radius at -dZ + double getRMax1 () const { return m_rMax1; } + // Outside radius at +dZ + double getRMax2 () const { return m_rMax2; } + // Half length in Z direction. + double getDZ () const { return m_dZ; } + // Starting angle of the segment in radians. + double getSPhi () const { return m_sPhi; } + // Delta angle of the segment in radians. + double getDPhi () const { return m_dPhi; } + +protected: + virtual ~GeoCons() = default; + private: - GeoCons(const GeoCons &right); - GeoCons & operator=(const GeoCons &right); - + + static const std::string s_classType; static const ShapeType s_classTypeID; - double m_rMin1; - double m_rMin2; - double m_rMax1; - double m_rMax2; - double m_dZ; - double m_sPhi; - double m_dPhi; + double m_rMin1{0.}; + double m_rMin2{0.}; + double m_rMax1{0.}; + double m_rMax2{0.}; + double m_dZ{0.}; + double m_sPhi{0.}; + double m_dPhi{0.}; }; -inline const std::string& GeoCons::getClassType () -{ - return s_classType; -} - -inline ShapeType GeoCons::getClassTypeID () -{ - return s_classTypeID; -} - -inline const double& GeoCons::getRMin1 () const -{ - return m_rMin1; -} - -inline const double& GeoCons::getRMin2 () const -{ - return m_rMin2; -} - -inline const double& GeoCons::getRMax1 () const -{ - return m_rMax1; -} - -inline const double& GeoCons::getRMax2 () const -{ - return m_rMax2; -} - -inline const double& GeoCons::getDZ () const -{ - return m_dZ; -} - -inline const double& GeoCons::getSPhi () const -{ - return m_sPhi; -} - -inline const double& GeoCons::getDPhi () const -{ - return m_dPhi; -} #endif diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoCutVolAction.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoCutVolAction.h index 802463b1ebc813aecd3db41349a036c8a86ff6b3..ceee9b8184e058a3f3a4ea710af0a78b0f5d562a 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoCutVolAction.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoCutVolAction.h @@ -32,17 +32,14 @@ * * Here is an example of GeoCutVolAction usage: * - * |--------------------------------------------------------------------------| - * | ... First construct a physical volume *origPhysVol* and add all daughter | - * | volumes to it | - * | | - * | GeoCutVolAction action(shape,transform); | - * | pPhysVol->apply(&action); | - * | GeoPhysVol* cutPhysVol = action.getPV(); | - * | pPhysVol->unref(); | - * | | - * | ... Use *cutPhysVol* afterwards (atach to the upper level volumes) | - * |--------------------------------------------------------------------------| + * |---------------------------------------------------------------------| + * | GeoPVLink pPhysVol; | + * | // ... add content to pPhysVol ... | + * | GeoCutVolAction action(shape,transform); | + * | pPhysVol->apply(&action); | + * | GeoPVLink cutPhysVol = action.getPV(); | + * | // Use cutPhysVol afterwards (atach to the upper level volumes) | + * |---------------------------------------------------------------------| */ #include "GeoModelKernel/GeoVPhysVol.h" diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoDefinitions.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoDefinitions.h index 0e31cdfe344a2784381a09acdd9bc29700e59f9e..cbc81fd9d4fb9ac7424c10951aee21e9a28e30f0 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoDefinitions.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoDefinitions.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration */ #ifndef GEOMODELKERNEL_GEODEFINITIONS_H @@ -16,27 +16,28 @@ #endif namespace GeoTrf { - typedef Eigen::Quaternion<double> Rotation3D; - typedef Eigen::Translation<double, 3> Translation3D; - typedef Eigen::AngleAxisd AngleAxis3D; - typedef Eigen::Affine3d Transform3D; - typedef Eigen::Matrix<double, 3, 1> Vector3D; - typedef Eigen::Matrix<double, 2, 1> Vector2D; - typedef Eigen::Matrix<double, 3, 3> RotationMatrix3D; - typedef Eigen::DiagonalMatrix <double, 3> Diagonal3DMatrix; + using Rotation3D = Eigen::Quaternion<double>; + using Translation3D = Eigen::Translation<double, 3>; + using AngleAxis3D = Eigen::AngleAxisd; + using Transform3D = Eigen::Affine3d; + template<size_t N> using VectorN = Eigen::Matrix<double, N, 1>; + using Vector3D = VectorN<3>; + using Vector2D = VectorN<2>; + using RotationMatrix3D = Eigen::Matrix<double, 3, 3>; + using Diagonal3DMatrix = Eigen::DiagonalMatrix <double, 3>; /// check if we can use Eigen Hyperplane for this struct Plane3D { protected: - double a_, b_, c_, d_; + double a_{0.}; + double b_{0.}; + double c_{1.}; + double d_{0.}; public: /** * Default constructor - creates plane z=0. */ - Plane3D() - : a_(0.), b_(0.), c_(1.), d_(0.) - {} - + Plane3D() = default; /** * Constructor from four numbers - creates plane a*x+b*y+c*z+d=0. */ Plane3D(double a1, double b1, double c1, double d1) @@ -72,7 +73,7 @@ namespace GeoTrf { Translate3D(double x, double y, double z) : Transform3D(Translation3D(x,y,z)) {} - virtual ~Translate3D() {} + virtual ~Translate3D() = default; }; class Scale3D : public Transform3D { @@ -80,7 +81,7 @@ namespace GeoTrf { Scale3D(double x, double y, double z) : Transform3D(Diagonal3DMatrix(x,y,z)) {} - virtual ~Scale3D() {} + virtual ~Scale3D() = default; }; class TranslateX3D : public Transform3D { @@ -88,7 +89,7 @@ namespace GeoTrf { TranslateX3D(double x) : Transform3D(Translation3D(x,0,0)) {} - virtual ~TranslateX3D() {} + virtual ~TranslateX3D() = default; }; class TranslateY3D : public Transform3D { @@ -96,7 +97,7 @@ namespace GeoTrf { TranslateY3D(double y) : Transform3D(Translation3D(0,y,0)) {} - virtual ~TranslateY3D() {} + virtual ~TranslateY3D() = default; }; class TranslateZ3D : public Transform3D { @@ -104,45 +105,147 @@ namespace GeoTrf { TranslateZ3D(double z) : Transform3D(Translation3D(0,0,z)) {} - virtual ~TranslateZ3D() {} + virtual ~TranslateZ3D() = default; }; + /** Starting from the three rotation matrices + * + * | 1 0 0 | + * R_{x}(\alpha) = | 0 cos(\alpha) -sin(\alpha) |, + * | 0 sin(\alpha) cos(\alpha) | + * + * | cos(\alpha) 0 sin(\alpha) | + * R_{y}(\alpha) = | 0 1 0 |, + * | -sin(\alpha) 0 cos(\alpha) | + * + * | cos(\alpha) -sin(\alpha) 0 | + * R_{z}(\alpha) = | sin(\alpha) cos(\alpha) 0 |, + * | 0 0 1 | + * + * a genericrotation can be either expressed in terms of the three rotation angles (\alpha, \beta, \gamma) + * + * R(\alpha, \beta, \gamma) = R_{z}(\gamma) * R_{y}(\beta) * R_{x}(\alpha) + * + * or as a function of the three rotation angles (\phi, \psi, \theta) + * + * R(\phi, \psi, \theta) = R_{z}(\phi) * R_{x}(\psi) * R_{z}(\phi) + * + * The first one is referred to as coordinate Euler angles and the second one is referred to geometric Euler angles + */ + inline RotationMatrix3D get3DRotMatX(const double angle) { + return RotationMatrix3D{AngleAxis3D{angle, Vector3D::UnitX()}}; + } + inline RotationMatrix3D get3DRotMatY(const double angle) { + return RotationMatrix3D{AngleAxis3D{angle, Vector3D::UnitY()}}; + } + inline RotationMatrix3D get3DRotMatZ(const double angle) { + return RotationMatrix3D{AngleAxis3D{angle, Vector3D::UnitZ()}}; + } class Rotate3D : public Transform3D { public: + /** @param angle: Rotation angle + * @param axis: Arbitrary rotation axis + */ Rotate3D(double angle, const Vector3D& axis) : Transform3D(AngleAxis3D(angle,axis)) {} - virtual ~Rotate3D() {} + virtual ~Rotate3D() = default; }; - + + /// @brief Rotation around the x-axis class RotateX3D : public Transform3D { public: RotateX3D(double angle) - : Transform3D(AngleAxis3D(angle,Vector3D::UnitX())) + : Transform3D(get3DRotMatX(angle)) {} - virtual ~RotateX3D() {} + virtual ~RotateX3D() = default; }; + /// @brief Rotation around the y-axis class RotateY3D : public Transform3D { public: RotateY3D(double angle) - : Transform3D(AngleAxis3D(angle,Vector3D::UnitY())) + : Transform3D(get3DRotMatY(angle)) {} - virtual ~RotateY3D() {} + virtual ~RotateY3D() = default; }; + /// @brief Rotation around the z-axis class RotateZ3D : public Transform3D { public: RotateZ3D(double angle) - : Transform3D(AngleAxis3D(angle,Vector3D::UnitZ())) + : Transform3D(get3DRotMatZ(angle)) {} - virtual ~RotateZ3D() {} + virtual ~RotateZ3D() = default; + }; + + /// @brief Representation of the Euler angles in the geometric description + struct EulerAngles{ + + EulerAngles() = default; + /// @brief Constructor taking the Euler angles values (phi, theta, psi) + EulerAngles(const double _ph, const double _th, const double _ps): + phi{_ph}, theta{_th}, psi{_ps} {} + /// @brief Rotation angle around the z-axis + double phi{0.}; + /// @brief Rotation angle around the y-axis + double theta{0.}; + /// @brief Rotation angle around the z-axis + double psi{0.}; + /// @brief Ordering operator to put the angles into a set + bool operator<(const EulerAngles& other) const; + /// @brief Simple comparison returning -1, 0, 1 + int compare(const EulerAngles& other) const; + operator bool() const; + }; + /// @brief Representation of the Euler angles in the coordinate description + struct CoordEulerAngles { + CoordEulerAngles() = default; + /// @brief Constructor taking the Euler angles values (alpha, beta, gamma) + CoordEulerAngles(const double _a, const double _b, const double _c): + alpha{_a}, beta{_b}, gamma{_c} {} + + /// @brief Rotation angles around the x-axis + double alpha{0.}; + /// @brief Rotation angle around the y-axis + double beta{0.}; + /// @brief Rotation angle around the z-axis + double gamma{0.}; + + /// @brief Ordering operator to put the angles into a set + bool operator<(const CoordEulerAngles& other) const; + /// @brief Simple comparison returning -1, 0, 1 + int compare(const CoordEulerAngles& other) const; + operator bool() const; + }; + + /// @brief Calculates the geometrical Euler angles + /// @param trans: Input transform + /// @return Euler angles in the geometrical representation + EulerAngles getGeoRotationAngles(const Transform3D& trans); + EulerAngles getGeoRotationAngles(const RotationMatrix3D& rotMat); + + /// @brief Calculates the coordinate Euler angles + /// @param trans: Input transform + /// @return Euler angles in the coordinate representation + CoordEulerAngles getCoordRotationAngles(const Transform3D& trans); + CoordEulerAngles getCoordRotationAngles(const RotationMatrix3D& rotMat); + + /// @brief Arbitrary rotation around an axis using the Euler angles class GeoRotation : public RotationMatrix3D { public: + /// @brief Constructor taking the Euler angles in the Geometrical representation + /// @param phi: Euler angle around the z-axis + /// @param theta: Euler angle around the x-axis + /// @param psi: Euler angle around the z-axis GeoRotation(double phi, double theta, double psi); - virtual ~GeoRotation() {} + + GeoRotation(const EulerAngles& angles); + GeoRotation(const CoordEulerAngles& angles); + + virtual ~GeoRotation() = default; }; class GeoTransformRT : public Transform3D { @@ -150,7 +253,7 @@ namespace GeoTrf { GeoTransformRT(const GeoRotation& rot, const Vector3D& trans) : Transform3D(Translation3D(trans)*Transform3D(AngleAxis3D(rot))) {} - virtual ~GeoTransformRT() {} + virtual ~GeoTransformRT() = default; }; } diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoEllipticalTube.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoEllipticalTube.h index a374b8e6db7372c8d8c063810c27cbdc97b8acaa..a36c03120eb393a9191be9eab739c460e5c6c89c 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoEllipticalTube.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoEllipticalTube.h @@ -7,73 +7,77 @@ /** * @class: GeoEllipticalTube - * + * * @brief This is a tube with elliptical cross section * The equation of the surface in x/y is 1.0 = (x/dx)**2 + (y/dy)**2 */ #include "GeoModelKernel/GeoShape.h" -class GeoEllipticalTube : public GeoShape -{ +class GeoEllipticalTube : public GeoShape { public: - GeoEllipticalTube(double XHalfLength, double YHalfLength, double ZHalfLength); + // Constructor for the ELLIPTICAL TUBE + GeoEllipticalTube(double XHalfLength, double YHalfLength, double ZHalfLength); + // Returns the volume of the shape, for mass inventory virtual double volume () const; - virtual const std::string & type () const; - virtual ShapeType typeID () const; + // Returns the bonding box of the shape + virtual void extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const; - virtual void exec (GeoShapeAction *action) const; + // Returns true if the shape contains the point, false otherwise. + virtual bool contains (double x, double y, double z) const; - static const std::string& getClassType (); - static ShapeType getClassTypeID (); + // Returns the ELLIPTICAL TUBE shape type, as a string + virtual const std::string & type () const{ + return getClassType(); + } - const double& getXHalfLength() const; - const double& getYHalfLength() const; - const double& getZHalfLength() const; + // Returns the ELLIPTICAL TUBE shape type, as a coded integer + virtual ShapeType typeID () const { + return getClassTypeID(); + } - protected: - virtual ~GeoEllipticalTube(); + // Executes a GeoShapeAction + virtual void exec (GeoShapeAction *action) const; - private: - - GeoEllipticalTube(const GeoEllipticalTube &right); - GeoEllipticalTube & operator=(const GeoEllipticalTube &right); + // For type identification + static const std::string& getClassType() { + return s_classType; + } - static const std::string s_classType; - static const ShapeType s_classTypeID; + // For type identification + static ShapeType getClassTypeID () { + return s_classTypeID; + } - double m_xHalfLength; - double m_yHalfLength; - double m_zHalfLength; -}; + // X semi-axis + double getXHalfLength() const { + return m_xHalfLength; + } + // Y semi-axis + double getYHalfLength() const { + return m_yHalfLength; + } -inline const std::string& GeoEllipticalTube::getClassType () -{ - return s_classType; -} + // Elliptical tube half-length in the Z direction + double getZHalfLength() const { + return m_zHalfLength; + } -inline ShapeType GeoEllipticalTube::getClassTypeID () -{ - return s_classTypeID; -} - -inline const double& GeoEllipticalTube::getXHalfLength() const -{ - return m_xHalfLength; -} + protected: + virtual ~GeoEllipticalTube() = default; -inline const double& GeoEllipticalTube::getYHalfLength() const -{ - return m_yHalfLength; -} + private: -inline const double& GeoEllipticalTube::getZHalfLength() const -{ - return m_zHalfLength; -} + static const std::string s_classType; + static const ShapeType s_classTypeID; + double m_xHalfLength{0.}; + double m_yHalfLength{0.}; + double m_zHalfLength{0.}; +}; #endif diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoFacet.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoFacet.h index 7baf2938173b0bc97d3fcfee43d11e56f365fc27..d73cb975fb47f7e5f9b33f320f504d51469ce816 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoFacet.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoFacet.h @@ -18,31 +18,34 @@ #include "GeoModelKernel/GeoDefinitions.h" #include <vector> -typedef GeoTrf::Vector3D GeoFacetVertex; +using GeoFacetVertex = GeoTrf::Vector3D; // ** Base class class GeoFacet : public RCBase { public: - enum GeoFacetVertexType - { + enum GeoFacetVertexType { ABSOLUTE, RELATIVE }; - inline size_t getNumberOfVertices() const; - inline GeoFacetVertex getVertex(size_t) const; - inline GeoFacetVertexType getVertexType() const; + inline size_t getNumberOfVertices() const { + return m_nVertices; + } + inline GeoFacetVertex getVertex(size_t index) const { + return (index<m_nVertices ? m_vertices[index] : GeoFacetVertex(999999.,999999.,999999.)); + } + inline GeoFacetVertexType getVertexType() const { + return m_vertexType; + } protected: - GeoFacet() - : m_nVertices(0), - m_vertexType(ABSOLUTE) {}; - virtual ~GeoFacet(){}; + GeoFacet() = default; + virtual ~GeoFacet() = default; - size_t m_nVertices; - std::vector<GeoFacetVertex> m_vertices; - GeoFacetVertexType m_vertexType; + size_t m_nVertices{0}; + std::vector<GeoFacetVertex> m_vertices{}; + GeoFacetVertexType m_vertexType{GeoFacetVertexType::ABSOLUTE}; }; // Triangular facet @@ -50,40 +53,21 @@ class GeoTriangularFacet : public GeoFacet { public: GeoTriangularFacet(GeoFacetVertex - ,GeoFacetVertex - ,GeoFacetVertex - ,GeoFacetVertexType); + ,GeoFacetVertex + ,GeoFacetVertex + ,GeoFacetVertexType); - virtual ~GeoTriangularFacet(); + virtual ~GeoTriangularFacet() = default; }; // Quadrangular facet -class GeoQuadrangularFacet : public GeoFacet -{ +class GeoQuadrangularFacet : public GeoFacet { public: - GeoQuadrangularFacet(GeoFacetVertex - ,GeoFacetVertex - ,GeoFacetVertex - ,GeoFacetVertex - ,GeoFacetVertexType); + GeoQuadrangularFacet(GeoFacetVertex ,GeoFacetVertex, GeoFacetVertex, + GeoFacetVertex ,GeoFacetVertexType); - virtual ~GeoQuadrangularFacet(); + virtual ~GeoQuadrangularFacet() = default; }; -// Inline methods -inline size_t GeoFacet::getNumberOfVertices() const -{ - return m_nVertices; -} - -inline GeoFacetVertex GeoFacet::getVertex(size_t index) const -{ - return (index<m_nVertices ? m_vertices[index] : GeoFacetVertex(999999.,999999.,999999.)); -} - -inline GeoFacet::GeoFacetVertexType GeoFacet::getVertexType() const -{ - return m_vertexType; -} #endif diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoFullPhysVol.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoFullPhysVol.h index 99a97794071c414a94be9911a127812d6e273976..03724c50c2f016f85c0f6e451e8d37151f7c2945 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoFullPhysVol.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoFullPhysVol.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #ifndef GEOMODELKERNEL_GEOFULLPHYSVOL_H @@ -59,12 +59,22 @@ class GeoFullPhysVol final : public GeoVFullPhysVol /// Returns the number of child physical volumes and Serial Transformers. virtual unsigned int getNChildVolAndST() const override; + /// Meaning of the input parameter 'attached' + /// TRUE: all cloned volumes are meant to stay identical to their clone origin for the lifetime + /// further changes are permitted neither in the origin nor in the clone results + /// + /// FALSE: use this value if you expect further changes in either clone origing or its clone results + /// which don't need to be syncronized. The clone origin and its clone are identical ONLY by + /// the time of cloning, further identity is not guaranteed GeoFullPhysVol* clone(bool attached = true); + const GeoFullPhysVol* cloneOrigin() const; + /// The following method breaks consistency of cloned volumes! /// Use it only in Simulation jobs and /// don't call it until geometry has been completely translated to G4 void clear(); // drop subtree + virtual GeoTrf::Transform3D getX (const GeoVAlignmentStore* store=nullptr) const override; virtual GeoTrf::Transform3D getDefX (const GeoVAlignmentStore* store=nullptr) const override; virtual unsigned int getNChildNodes() const override; @@ -72,16 +82,14 @@ class GeoFullPhysVol final : public GeoVFullPhysVol virtual const GeoGraphNode * const *findChildNode(const GeoGraphNode *n) const override; protected: - virtual ~GeoFullPhysVol() override; + virtual ~GeoFullPhysVol() = default; private: - GeoFullPhysVol(const GeoFullPhysVol &right); - GeoFullPhysVol & operator=(const GeoFullPhysVol &right); - + /// Hold the list of children. - std::vector<const GeoGraphNode *> m_daughters; + std::vector<GeoIntrusivePtr<GeoGraphNode>> m_daughters{}; - const GeoFullPhysVol* m_cloneOrigin; + const GeoFullPhysVol* m_cloneOrigin{nullptr}; }; #endif diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoGenericTrap.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoGenericTrap.h index 7db180074407007f0d2951ab6be2cb6288836dca..edbc1c077db9d52c587f421407eaedc17c32f42e 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoGenericTrap.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoGenericTrap.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #ifndef GEOMODELKERNEL_GEOGENERICTRAP_H @@ -9,49 +9,66 @@ #include "GeoModelKernel/GeoDefinitions.h" #include <vector> -typedef GeoTrf::Vector2D GeoTwoVector; -typedef std::vector<GeoTwoVector> GeoGenericTrapVertices; +using GeoTwoVector = GeoTrf::Vector2D ; +using GeoGenericTrapVertices = std::vector<GeoTwoVector>; -class GeoGenericTrap : public GeoShape -{ +class GeoGenericTrap : public GeoShape { public: GeoGenericTrap(double ZHalfLength, const GeoGenericTrapVertices& Vertices); + // Returns the volume of the shape, for mass inventory. virtual double volume() const; - virtual const std::string& type() const; - virtual ShapeType typeID() const; + // Returns the bonding box of the shape. + virtual void extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const; - static const std::string& getClassType(); - static ShapeType getClassTypeID(); + // Returns true if the shape contains the point, false otherwise. + virtual bool contains (double x, double y, double z) const; + // Returns the GENERIC TRAP shape type, as a string. + virtual const std::string& type() const{ + return getClassType(); + } + + // Returns the GENERIC TRAP shape type, as a coded integer. + virtual ShapeType typeID() const{ + return getClassTypeID(); + } + + // For type identification. + static const std::string& getClassType() { + return s_classType; + } + + // For type identification. + static ShapeType getClassTypeID() { + return s_classTypeID; + } + + // Executes a GeoShapeAction. virtual void exec(GeoShapeAction *action) const; - double getZHalfLength() const; - const GeoGenericTrapVertices& getVertices() const; + // Z half length. + double getZHalfLength() const{ + return m_zHalfLength; + } + + // Vector of vertices. + const GeoGenericTrapVertices& getVertices() const { + return m_vertices; + } protected: - virtual ~GeoGenericTrap(); + virtual ~GeoGenericTrap() = default; private: - GeoGenericTrap(const GeoGenericTrap &right); - GeoGenericTrap& operator=(const GeoGenericTrap &right); static const std::string s_classType; static const ShapeType s_classTypeID; - double m_zHalfLength; - GeoGenericTrapVertices m_vertices; + double m_zHalfLength{0}; + GeoGenericTrapVertices m_vertices{}; }; -inline const std::string& GeoGenericTrap::getClassType() -{ - return s_classType; -} - -inline ShapeType GeoGenericTrap::getClassTypeID() -{ - return s_classTypeID; -} - #endif diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoGeometryPluginLoader.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoGeometryPluginLoader.h index 3e39620e8c6402995594295d37fe0378b55cd288..73b0b93bd0152c9681c1be013e5f4d590b4e6af3 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoGeometryPluginLoader.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoGeometryPluginLoader.h @@ -5,5 +5,6 @@ #ifndef GEOGEOMETRYPLUGINLOADER_H_ #define GEOGEOMETRYPLUGINLOADER_H_ #include "GeoModelKernel/GeoPluginLoader.h" +#include "GeoModelKernel/GeoVGeometryPlugin.h" typedef GeoPluginLoader<GeoVGeometryPlugin> GeoGeometryPluginLoader; #endif diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoGraphNode.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoGraphNode.h index 2f72979fdad096e36ce0be8c5fd9d88c17301172..1f8a2ae52ea942e9690b256b33f87895e40bd4a1 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoGraphNode.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoGraphNode.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #ifndef GEOMODELKERNEL_GEOGRAPHNODE_H @@ -25,10 +25,9 @@ class GeoNodeAction; class GeoVPhysVol; -class GeoGraphNode : public RCBase -{ +class GeoGraphNode : public RCBase { public: - GeoGraphNode (); + GeoGraphNode () = default; // Executes a GeoNodeAction. virtual void exec (GeoNodeAction *action) const; @@ -42,11 +41,8 @@ class GeoGraphNode : public RCBase virtual void dockTo (GeoVPhysVol* ); protected: - virtual ~GeoGraphNode(); + virtual ~GeoGraphNode() = default; - private: - GeoGraphNode(const GeoGraphNode &right); - GeoGraphNode & operator=(const GeoGraphNode &right); }; #endif diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoIntrusivePtr.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoIntrusivePtr.h new file mode 100644 index 0000000000000000000000000000000000000000..728767d358a5980bd679278f65769ade324a0178 --- /dev/null +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoIntrusivePtr.h @@ -0,0 +1,126 @@ +/* + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration +*/ +#ifndef GEOMODELKERNEL_GeoIntrusivePtr_H +#define GEOMODELKERNEL_GeoIntrusivePtr_H + +#include <GeoModelKernel/RCBase.h> +#include <type_traits> + +#include <utility> + + +template<typename GeoType> +class GeoIntrusivePtr{ + public: + template <typename GeoTypeGrp> friend class GeoIntrusivePtr; + + explicit GeoIntrusivePtr() noexcept = default; + // Standard constructor taking a bare pointer + GeoIntrusivePtr(GeoType* obj) noexcept: + m_ptr{obj} { + if (m_ptr) obj->ref(); + } + /// Copy constructor + explicit GeoIntrusivePtr(const GeoIntrusivePtr& other) noexcept: + GeoIntrusivePtr{other.get()} {} + + /// Copy constructor for derived types + template <typename GeoTypeGrp, + typename = typename std::enable_if<!std::is_same<GeoType,GeoTypeGrp>::value, bool>> + GeoIntrusivePtr(const GeoIntrusivePtr<GeoTypeGrp>& other) noexcept: + GeoIntrusivePtr{other.get()} {} + + /// Move constructor + explicit GeoIntrusivePtr(GeoIntrusivePtr&& other) noexcept: + m_ptr{other.m_ptr} { + other.m_ptr = nullptr; + } + /// Move constructor for derived types + template <typename GeoTypeGrp, + typename = typename std::enable_if<!std::is_same<GeoType,GeoTypeGrp>::value, bool>> + GeoIntrusivePtr(GeoIntrusivePtr<GeoTypeGrp>&& other) noexcept: + m_ptr{other.m_ptr} { + other.m_ptr = nullptr; + } + + + /// Assignment operator + GeoIntrusivePtr& operator=(const GeoIntrusivePtr& other) noexcept { + reset(other.get()); + return *this; + } + template <typename GeoTypeGrp, + typename = typename std::enable_if<!std::is_same<GeoType,GeoTypeGrp>::value, bool>> + GeoIntrusivePtr& operator=(const GeoIntrusivePtr<GeoTypeGrp>& other) { + reset(other.get()); + return *this; + } + + GeoIntrusivePtr& operator=(GeoType* other) noexcept { + reset(other); + return *this; + } + /// Move assignment operator + GeoIntrusivePtr& operator=(GeoIntrusivePtr&& other) { + if (m_ptr && m_ptr == other.get()) { + m_ptr->unref(); + } else { + m_ptr = other.get(); + } + other.m_ptr = nullptr; + return *this; + } + template <typename GeoTypeGrp, + typename = typename std::enable_if<!std::is_same<GeoType,GeoTypeGrp>::value, bool>> + GeoIntrusivePtr& operator=(GeoIntrusivePtr<GeoTypeGrp>&& other) { + if (m_ptr && m_ptr == other.get()) { + m_ptr->unref(); + } else { + m_ptr = other.get(); + } + other.m_ptr = nullptr; + return *this; + } + /// Reset the pointer + void reset(GeoType* ptr = nullptr) { + if (m_ptr == ptr) return; + if (m_ptr) m_ptr->unref(); + m_ptr = ptr; + if (m_ptr) m_ptr->ref(); + } + /// Destructor + ~GeoIntrusivePtr() { + if (m_ptr) m_ptr->unref(); + } + /// Implicit conversion + operator GeoType*() const { return m_ptr; } + operator GeoType* const*() const { return &m_ptr; } + + /// Pointer access + GeoType* operator->() const { return m_ptr; } + /// Dereference the pointer + GeoType& operator*() const { return *m_ptr; } + /// Getter methods + GeoType* get() const { return m_ptr; } + /// Validity operator + operator bool () const { return m_ptr != nullptr; } + /// Invalidity operator + bool operator!() const { return !m_ptr; } + /// Comparison operator + // template <class GeoTypeGrp> + // bool operator==(const GeoIntrusivePtr<GeoTypeGrp>& other) const { + // return m_ptr == other.m_ptr; + // } + bool operator==(GeoType* other) const { + return m_ptr == other; + } + /// Odering operator + bool operator<(const GeoIntrusivePtr& other) const { + return m_ptr < other.m_ptr; + } + private: + GeoType* m_ptr{nullptr}; +}; + +#endif \ No newline at end of file diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoLogVol.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoLogVol.h index 3c38abd2055d31c5ba040880cfe5e19f345450fb..cb3b5a3e90e3b409e71e93d3c86200360637d373 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoLogVol.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoLogVol.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #ifndef GEOMODELKERNEL_GEOLOGVOL_H @@ -14,6 +14,7 @@ #include "GeoModelKernel/GeoShape.h" #include "GeoModelKernel/RCBase.h" +#include "GeoModelKernel/GeoIntrusivePtr.h" #include "GeoModelKernel/GeoMaterial.h" #include <vector> @@ -23,44 +24,34 @@ class GeoLogVol : public RCBase GeoLogVol (const std::string &Name, const GeoShape *Shape, const GeoMaterial *Material); // Returns the name of the logical volume. - const std::string & getName () const; + const std::string & getName () const { + return m_name; + } // Returns the shape of the logical volume. - const GeoShape * getShape () const; + const GeoShape* getShape () const { + return m_shape; + } // Returns the material of the logical volume. - const GeoMaterial * getMaterial () const; + const GeoMaterial* getMaterial () const { + return m_material; + } protected: - virtual ~GeoLogVol(); + virtual ~GeoLogVol() = default; private: - GeoLogVol(const GeoLogVol &right); - GeoLogVol & operator=(const GeoLogVol &right); // The name of the logical volume. - std::string m_name; + std::string m_name{}; // Material composition of this volume. - const GeoMaterial *m_material; + GeoIntrusivePtr<const GeoMaterial> m_material{}; // Shape of this volume. - const GeoShape *m_shape; + GeoIntrusivePtr<const GeoShape> m_shape{}; }; -inline const std::string & GeoLogVol::getName () const -{ - return m_name; -} - -inline const GeoShape * GeoLogVol::getShape () const -{ - return m_shape; -} - -inline const GeoMaterial * GeoLogVol::getMaterial () const -{ - return m_material; -} #endif diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoMaterial.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoMaterial.h index 1a328fd896f261de29ff60b4c914e0f7abe3935b..f7ee8632ba8280b2b65c1d38d3e10b14b7b436cb 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoMaterial.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoMaterial.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #ifndef GEOMODELKERNEL_GEOMATERIAL_H @@ -28,12 +28,13 @@ #include "GeoModelKernel/RCBase.h" #include "GeoModelKernel/GeoElement.h" +#include "GeoModelKernel/GeoIntrusivePtr.h" #include <vector> class GeoMaterial : public RCBase { public: - GeoMaterial (const std::string &Name, double Density); + GeoMaterial (const std::string& name, double density); // Add an element to the material. void add (const GeoElement* element, double fraction = 1.0); @@ -63,7 +64,8 @@ class GeoMaterial : public RCBase // Return the nuclear interaction length, computed from the // density, the list of constituents, and their properties. double getIntLength () const; - + + // Return the number of elements unsigned int getNumElements () const; // Gets the ith element. @@ -83,45 +85,44 @@ class GeoMaterial : public RCBase const unsigned int& getID () const; protected: - virtual ~GeoMaterial(); + virtual ~GeoMaterial() = default; private: - GeoMaterial(const GeoMaterial &right); - GeoMaterial & operator=(const GeoMaterial &right); + GeoMaterial() = delete; + GeoMaterial(const GeoMaterial &right) = delete; + GeoMaterial & operator=(const GeoMaterial &right) = delete; - std::string m_name; - double m_density; - unsigned int m_iD; + std::string m_name{}; + double m_density{0.}; + unsigned int m_iD{0}; // A list of the fractional composition of each material. // Fraction is by mass. - std::vector<double> m_fraction; + std::vector<double> m_fractions; // The radiation length of the material. - double m_radLength; + double m_radLength{0.}; // The interaction length of the material. - double m_intLength; - - // A static used to assign unique identifiers to new - // materials. - static unsigned int s_lastID; + double m_intLength{0.}; // The constant term in the formula governing dE/dx. - double m_dedDxConst; + double m_dedDxConst{0.}; // The ionization potential in the formula governing dE/dx. - double m_deDxI0; + double m_deDxI0{0.}; // A flag used to lock the material from further addition // of elements or other constituents. - bool m_locked; - - static const double s_ionizationPotential[93]; + bool m_locked{false}; - private: // The list of GeoElements composing a GeoMaterial. - std::vector<const GeoElement *> m_element; + std::vector<GeoIntrusivePtr<const GeoElement>> m_elements; + + // A static used to assign unique identifiers to new materials. + static unsigned int s_lastID; + + static const double s_ionizationPotential[93]; }; inline const std::string& GeoMaterial::getName () const diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoPVConstLink.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoPVConstLink.h deleted file mode 100644 index efb2c0424786bcb8c872c65b1b15a78a336b7695..0000000000000000000000000000000000000000 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoPVConstLink.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -*/ - -#ifndef GEOMODELKERNEL_GEOPVCONSTLINK_H -#define GEOMODELKERNEL_GEOPVCONSTLINK_H - -/** - * @class GeoPVConstLink - * - * @brief Smart pointer to physical volume... constant - */ - -class GeoVPhysVol; - -class GeoPVConstLink -{ - public: - GeoPVConstLink(); - GeoPVConstLink(const GeoPVConstLink &right); - GeoPVConstLink (const GeoVPhysVol *addr); - - virtual ~GeoPVConstLink(); - - int operator==(const GeoPVConstLink &right) const; - int operator!=(const GeoPVConstLink &right) const; - - int operator<(const GeoPVConstLink &right) const; - int operator>(const GeoPVConstLink &right) const; - int operator<=(const GeoPVConstLink &right) const; - int operator>=(const GeoPVConstLink &right) const; - - // Dereference this smart pointer, like a regular pointer. - virtual const GeoVPhysVol & operator * () const; - - // Allow use of smartPointer->operation()..... - virtual const GeoVPhysVol * operator -> () const; - - operator bool () const; - - GeoPVConstLink& operator = (const GeoPVConstLink& right); - - protected: - // A pointer to the underlying volume - GeoVPhysVol * m_ptr; - -}; - -#endif diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoPVLink.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoPVLink.h deleted file mode 100644 index af94674fe9187a6db5948512ad8f9cc1d2b1e6fe..0000000000000000000000000000000000000000 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoPVLink.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -*/ - -#ifndef GEOMODELKERNEL_GEOPVLINK_H -#define GEOMODELKERNEL_GEOPVLINK_H - -/** - * @class GeoPVConstLink - * - * @brief Smart pointer to physical volume... non-constant - */ - -#include "GeoModelKernel/GeoPVConstLink.h" - -class GeoPVLink : public GeoPVConstLink -{ - public: - GeoPVLink(); - GeoPVLink(const GeoPVLink &right); - GeoPVLink (const GeoVPhysVol *addr); - - virtual ~GeoPVLink(); - - // Dereference this smart pointer, like a regular pointer. - virtual GeoVPhysVol & operator * (); - - // Allow use of smartPointer->operation()..... - virtual GeoVPhysVol * operator -> (); - - // Dereference this smart pointer, like a regular pointer. - virtual const GeoVPhysVol & operator * () const; - - // Allow use of smartPointer->operation()..... - virtual const GeoVPhysVol * operator -> () const; - - // Assignment operator. - GeoPVLink& operator = (const GeoPVLink& right); -}; - - -#endif diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoPara.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoPara.h index 7072aee43ce53ba6fd65af0aac16541152363b96..26ad8555e7a937223f21eec27c125f655616a492 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoPara.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoPara.h @@ -10,102 +10,87 @@ class GeoPara : public GeoShape { public: - // Constructor for the BOX. + // Constructor for the BOX. GeoPara (double XHalfLength, double YHalfLength, double ZHalfLength, double Alpha, double Theta, double Phi); - - // Returns the volume of the shape, for mass inventory + + // Returns the volume of the shape, for mass inventory. virtual double volume () const; - - // Returns the PARA shape type, as a string. - virtual const std::string & type () const; - - // Returns the PARA shape type, as a coded integer. - virtual ShapeType typeID () const; - - // Executes a GeoShapeAction + + // Returns the bonding box of the shape. + virtual void extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const; + + // Returns true if the shape contains the point, false otherwise. + virtual bool contains (double x, double y, double z) const; + + // Returns the PARA shape type, as a string. + virtual const std::string & type () const { + return getClassType(); + } + + // Returns the PARA shape type, as a coded integer. + virtual ShapeType typeID () const { + return getClassTypeID(); + } + + // Executes a GeoShapeAction virtual void exec (GeoShapeAction *action) const; - - // For type identification. - static const std::string& getClassType (); - - // For type identification. - static ShapeType getClassTypeID (); - - // Half length in the x-direction. - const double& getXHalfLength () const; - - // Half-length in the y direction. - const double& getYHalfLength () const; - - // Half-length in the z direction. - const double& getZHalfLength () const; - - // Polar (theta) angle. - const double& getTheta () const; - - // The angle alpha...between the two sides of the top face - // of the parallelapiped. - const double& getAlpha () const; - - // Azimuthal (phi) angle. - const double& getPhi () const; - - protected: - virtual ~GeoPara(); - - private: - GeoPara(const GeoPara &right); - GeoPara & operator=(const GeoPara &right); - - static const std::string s_classType; - static const ShapeType s_classTypeID; - double m_xHalfLength; - double m_yHalfLength; - double m_zHalfLength; - double m_theta; - double m_alpha; - double m_phi; -}; + // For type identification. + static const std::string& getClassType (){ + return s_classType; + } -inline const std::string& GeoPara::getClassType () -{ - return s_classType; -} + // For type identification. + static ShapeType getClassTypeID () { + return s_classTypeID; + } -inline ShapeType GeoPara::getClassTypeID () -{ - return s_classTypeID; -} + // Half length in the x-direction. + double getXHalfLength () const { + return m_xHalfLength; + } -inline const double& GeoPara::getXHalfLength () const -{ - return m_xHalfLength; -} + // Half-length in the y direction. + double getYHalfLength () const { + return m_yHalfLength; + } -inline const double& GeoPara::getYHalfLength () const -{ - return m_yHalfLength; -} + // Half-length in the z direction. + double getZHalfLength() const { + return m_zHalfLength; + } -inline const double& GeoPara::getZHalfLength () const -{ - return m_zHalfLength; -} + // Polar (theta) angle. + double getTheta() const{ + return m_theta; + } -inline const double& GeoPara::getTheta () const -{ - return m_theta; -} + // The angle alpha...between the two sides of the top face + // of the parallelapiped. + double getAlpha () const { + return m_alpha; + } -inline const double& GeoPara::getAlpha () const -{ - return m_alpha; -} + // Azimuthal (phi) angle. + double getPhi () const{ + return m_phi; + } -inline const double& GeoPara::getPhi () const -{ - return m_phi; -} + protected: + virtual ~GeoPara() = default; + + private: + + static const std::string s_classType; + static const ShapeType s_classTypeID; + + double m_xHalfLength{0.}; + double m_yHalfLength{0.}; + double m_zHalfLength{0.}; + double m_theta{0.}; + double m_alpha{0.}; + double m_phi{0.}; +}; #endif diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoPcon.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoPcon.h index c08797c8d8fefca975fd148c8d2089663adbe21a..59b88f989bbda1cda986f6e00c642d7cbb60133f 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoPcon.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoPcon.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration */ #ifndef GEOMODELKERNEL_GEOPCON_H @@ -10,132 +10,114 @@ * * @brief This shape represents a polycone. * Specify the starting angle and delta angle (subtended angle) - * of the polycone first, Then add at least two planes with the + * of the polycone first, then add at least two planes with the * addPlane( double zPlane, double rInner, double rOuter) method. */ #include "GeoModelKernel/GeoShape.h" #include <vector> -class GeoPcon : public GeoShape -{ +class GeoPcon : public GeoShape { public: - // Constructor for the PCON. Note that the constructor - // does not fully build this object. The PCON is not valid - // until at least two polygon planes have been added. + // Constructor for the PCON. Note that the constructor + // does not fully build this object. The PCON is not valid + // until at least two polygon planes have been added. GeoPcon (double SPhi, double DPhi); - // Returns the volume of the shape, for mass inventory + // Returns the volume of the shape, for mass inventory virtual double volume () const; - - // Returns the PCON shape type, as a string. - virtual const std::string & type () const; - - // Returns the PCON shape type, as a coded integer. - virtual ShapeType typeID () const; - - // Add another plane to the polycone A minimum of two - // planes are required to create a valid polycone. + + // Returns the bonding box of the shape + virtual void extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const; + + // Returns true if the shape contains the point, false otherwise. + virtual bool contains (double x, double y, double z) const; + + // Returns the PCON shape type, as a string. + virtual const std::string& type() const { + return getClassType(); + } + + // Returns the PCON shape type, as a coded integer. + virtual ShapeType typeID() const { + return getClassTypeID(); + } + + // Add another plane to the polycone A minimum of two + // planes are required to create a valid polycone. void addPlane (double ZPlane, double RMinPlane, double RMaxPlane); - - // Returns the number of planes that have been created for - // the polycone. - unsigned int getNPlanes () const; - - // True if the polycone has at least two planes. False - // otherwise. - bool isValid () const; - - // Get the Z Position of the specified plane. - const double & getZPlane (unsigned int i) const; - - // Get the RMin of the specified plane. - const double & getRMinPlane (unsigned int i) const; - - // Get the Z Position of the specified plane. - const double & getRMaxPlane (unsigned int i) const; - - // Executes a GeoShapeAction + + // Returns the number of planes that have been created for + // the polycone. + unsigned int getNPlanes() const { + return m_zPlane.size(); + } + + // True if the polycone has at least two planes. False + // otherwise. + bool isValid() const { + return getNPlanes() >= 2; + } + + // Get the Z Position of the specified plane. + double getZPlane(unsigned int i) const { + return m_zPlane[i]; + } + + // Get the RMin of the specified plane. + double getRMinPlane(unsigned int i) const { + return m_rMinPlane[i]; + } + + // Get the Z Position of the specified plane. + double getRMaxPlane(unsigned int i) const { + return m_rMaxPlane[i]; + } + + // Executes a GeoShapeAction virtual void exec (GeoShapeAction *action) const; - - // For type identification. - static const std::string& getClassType (); - - // For type identification. - static ShapeType getClassTypeID (); - - // Starting angle of the segment in radians. - const double& getSPhi () const; - - // Delta angle of the segment in radians. - const double& getDPhi () const; + + // For type identification. + static const std::string& getClassType() { + return s_classType; + } + + // For type identification. + static ShapeType getClassTypeID() { + return s_classTypeID; + } + + // Starting angle of the segment in radians. + double getSPhi() const { + return m_sPhi; + } + + // Delta angle of the segment in radians. + double getDPhi() const { + return m_dPhi; + } protected: - virtual ~GeoPcon(); - + virtual ~GeoPcon() = default; + private: - GeoPcon(const GeoPcon &right); - GeoPcon & operator=(const GeoPcon &right); - + static const std::string s_classType; static const ShapeType s_classTypeID; - double m_sPhi; - double m_dPhi; + double m_sPhi{0.}; + double m_dPhi{0.}; + + // Z Position of poly-cone planes. + std::vector<double> m_zPlane{}; - // Z Position of poly-cone planes. - std::vector<double> m_zPlane; - - // Minimum radius of poly-cone planes. - std::vector<double> m_rMinPlane; + // Minimum radius of poly-cone planes. + std::vector<double> m_rMinPlane{}; - // Maximum radius of poly-cone planes. - std::vector<double> m_rMaxPlane; + // Maximum radius of poly-cone planes. + std::vector<double> m_rMaxPlane{}; }; -inline unsigned int GeoPcon::getNPlanes () const -{ - return m_zPlane.size (); -} - -inline bool GeoPcon::isValid () const -{ - return getNPlanes () >= 2; -} - -inline const double & GeoPcon::getZPlane (unsigned int i) const -{ - return m_zPlane[i]; -} - -inline const double & GeoPcon::getRMinPlane (unsigned int i) const -{ - return m_rMinPlane[i]; -} - -inline const double & GeoPcon::getRMaxPlane (unsigned int i) const -{ - return m_rMaxPlane[i]; -} - -inline const std::string& GeoPcon::getClassType () -{ - return s_classType; -} - -inline ShapeType GeoPcon::getClassTypeID () -{ - return s_classTypeID; -} - -inline const double& GeoPcon::getSPhi () const -{ - return m_sPhi; -} - -inline const double& GeoPcon::getDPhi () const -{ - return m_dPhi; -} #endif diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoPgon.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoPgon.h index 12f22cb28afea3254618d157e9a12df7d5b129ca..7dea7fad2eb73b4ee8bb79968a050900e40fe2ff 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoPgon.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoPgon.h @@ -11,131 +11,110 @@ class GeoPgon : public GeoShape { public: - // Constructor for the PGON. Note that the constructor - // does not fully build this object. The PGON is not valid - // until at least two polygon planes have been added. + // Constructor for the PGON. Note that the constructor + // does not fully build this object. The PGON is not valid + // until at least two polygon planes have been added. GeoPgon (double SPhi, double DPhi, unsigned int NSides); - // Returns the volume of the shape, for mass inventory + // Returns the volume of the shape, for mass inventory virtual double volume () const; - - // Returns the PGON shape type, as a string. - virtual const std::string & type () const; - - // Returns the PGON shape type, as a coded integer. - virtual ShapeType typeID () const; - - // Add another plane to the polygon. A minimum of two - // planes are required to create a valid polygon. - void addPlane (double ZPlane, double RMinPlane, double RMaxPlane); - - // Returns the number of planes that have been created for - // the polygon. - unsigned int getNPlanes () const; - - // True if the polygon has at least two planes. False - // otherwise. - bool isValid () const; - - // Get the Z Position of the specified plane. - const double & getZPlane (unsigned int i) const; - - // Get the RMin of the specified plane. - const double & getRMinPlane (unsigned int i) const; - - // Get the Z Position of the specified plane. - const double & getRMaxPlane (unsigned int i) const; - - // Executes a GeoShapeAction - virtual void exec (GeoShapeAction *action) const; - - // For type identification. - static const std::string& getClassType (); - - // For type identification. - static ShapeType getClassTypeID (); - - // Starting angle of the segment in radians. - const double& getSPhi () const; - - // Delta angle of the segment in radians. - const double& getDPhi () const; - - // Number of sides in each polygonal segment. - const unsigned int& getNSides () const; - - protected: - virtual ~GeoPgon(); - - private: - GeoPgon(const GeoPgon &right); - GeoPgon & operator=(const GeoPgon &right); - - static const std::string s_classType; - static const ShapeType s_classTypeID; - double m_sPhi; - double m_dPhi; - unsigned int m_nSides; + // Returns the bonding box of the shape + virtual void extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const; - // Z Position of polygon planes. - std::vector<double> m_zPlane; + // Returns true if the shape contains the point, false otherwise. + virtual bool contains (double x, double y, double z) const; - // Minimum radius of polygon planes. - std::vector<double> m_rMinPlane; + // Returns the PGON shape type, as a string. + virtual const std::string & type() const { + return getClassType(); + } - // Maximum radius of polygon planes. - std::vector<double> m_rMaxPlane; -}; + // Returns the PGON shape type, as a coded integer. + virtual ShapeType typeID() const { + return getClassTypeID(); + } -inline unsigned int GeoPgon::getNPlanes () const -{ - return m_zPlane.size (); -} + // Add another plane to the polygon. A minimum of two + // planes are required to create a valid polygon. + void addPlane (double ZPlane, double RMinPlane, double RMaxPlane); -inline bool GeoPgon::isValid () const -{ - return m_zPlane.size () >= 2; -} + // Returns the number of planes that have been created for + // the polygon. + unsigned int getNPlanes() const { + return m_zPlane.size (); + } + + // True if the polygon has at least two planes. False + // otherwise. + bool isValid() const { + return m_zPlane.size () >= 2; + } + + // Get the Z Position of the specified plane. + double getZPlane (unsigned int i) const { + return m_zPlane[i]; + } + + // Get the RMin of the specified plane. + double getRMinPlane (unsigned int i) const { + return m_rMinPlane[i]; + } + + // Get the Z Position of the specified plane. + double getRMaxPlane (unsigned int i) const { + return m_rMaxPlane[i]; + } + + // Executes a GeoShapeAction + virtual void exec (GeoShapeAction *action) const; -inline const double & GeoPgon::getZPlane (unsigned int i) const -{ - return m_zPlane[i]; -} + // For type identification. + static const std::string& getClassType() { + return s_classType; + } -inline const double & GeoPgon::getRMinPlane (unsigned int i) const -{ - return m_rMinPlane[i]; -} + // For type identification. + static ShapeType getClassTypeID() { + return s_classTypeID; + } -inline const double & GeoPgon::getRMaxPlane (unsigned int i) const -{ - return m_rMaxPlane[i]; -} + // Starting angle of the segment in radians. + double getSPhi() const { + return m_sPhi; + } -inline const std::string& GeoPgon::getClassType () -{ - return s_classType; -} + // Delta angle of the segment in radians. + double getDPhi() const { + return m_dPhi; + } -inline ShapeType GeoPgon::getClassTypeID () -{ - return s_classTypeID; -} + // Number of sides in each polygonal segment. + unsigned int getNSides () const{ + return m_nSides; + } -inline const double& GeoPgon::getSPhi () const -{ - return m_sPhi; -} + protected: + virtual ~GeoPgon() = default; -inline const double& GeoPgon::getDPhi () const -{ - return m_dPhi; -} + private: + + static const std::string s_classType; + static const ShapeType s_classTypeID; -inline const unsigned int& GeoPgon::getNSides () const -{ - return m_nSides; -} + double m_sPhi{0.}; + double m_dPhi{0.}; + unsigned int m_nSides{0}; + + // Z Position of polygon planes. + std::vector<double> m_zPlane{}; + + // Minimum radius of polygon planes. + std::vector<double> m_rMinPlane{}; + + // Maximum radius of polygon planes. + std::vector<double> m_rMaxPlane{}; +}; #endif diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoPhysVol.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoPhysVol.h index bd2ac00fd6c7b6df49dfa844034f78bdff67526c..2e5988637d10add49e3a22dc1214487d1354055f 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoPhysVol.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoPhysVol.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #ifndef GEOMODELKERNEL_GEOPHYSVOL_H @@ -28,14 +28,10 @@ #include <mutex> -class GeoPhysVol : public GeoVPhysVol -{ +class GeoPhysVol : public GeoVPhysVol { public: GeoPhysVol(const GeoLogVol* LogVol); - GeoPhysVol(const GeoPhysVol &right) = delete; - GeoPhysVol & operator=(const GeoPhysVol &right) = delete; - /// Adds a Graph Node to the Geometry Graph virtual void add(GeoGraphNode* graphNode) override final; @@ -72,10 +68,10 @@ class GeoPhysVol : public GeoVPhysVol virtual const GeoGraphNode * const *findChildNode(const GeoGraphNode *n) const override final; protected: - virtual ~GeoPhysVol() override; + virtual ~GeoPhysVol() = default; private: - std::vector<const GeoGraphNode*> m_daughters; + std::vector<GeoIntrusivePtr<GeoGraphNode>> m_daughters{}; mutable std::mutex m_muxVec; }; diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoPluginLoader.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoPluginLoader.h index e0ea899aa6277f1e9cd47e29572db1a105b7d2a1..4470c8c49300701061a3357731d3c102e1346585 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoPluginLoader.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoPluginLoader.h @@ -16,7 +16,7 @@ template <class Plugin> class GeoPluginLoader public: // Constructor: - GeoPluginLoader<Plugin>(); + GeoPluginLoader(); // Destructor: ~GeoPluginLoader(); diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoPolyhedron.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoPolyhedron.h index 40599c71f702a62127162bf1f37ddf776a1a7590..06bf1f3d5e3adc44aa58d19cd488cdab9c39f968 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoPolyhedron.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoPolyhedron.h @@ -165,41 +165,43 @@ #define DEFAULT_NUMBER_OF_STEPS 24 #endif -class GeoFacet -{ - friend class GeoPolyhedron; - friend std::ostream & operator<< (std::ostream &, const GeoFacet & facet); - -private: - struct - { - int v, f; - } - m_edge[4]; - -public: - GeoFacet (int v1 = 0, int f1 = 0, int v2 = 0, int f2 = 0, - int v3 = 0, int f3 = 0, int v4 = 0, int f4 = 0) - { - m_edge[0].v = v1; - m_edge[0].f = f1; - m_edge[1].v = v2; - m_edge[1].f = f2; - m_edge[2].v = v3; - m_edge[2].f = f3; - m_edge[3].v = v4; - m_edge[3].f = f4; - } -}; - class GeoPolyhedron { + friend class Geo_BooleanProcessor; friend std::ostream & operator<< (std::ostream &, const GeoPolyhedron & ph); private: static int s_fNumberOfRotationSteps; protected: + class GeoFacet + { + friend class GeoPolyhedron; + friend std::ostream & operator<< (std::ostream &, const GeoFacet & facet); + + private: + struct + { + int v, f; + } + m_edge[4]; + + public: + GeoFacet (int v1 = 0, int f1 = 0, int v2 = 0, int f2 = 0, + int v3 = 0, int f3 = 0, int v4 = 0, int f4 = 0) + { + m_edge[0].v = v1; + m_edge[0].f = f1; + m_edge[1].v = v2; + m_edge[1].f = f2; + m_edge[2].v = v3; + m_edge[2].f = f3; + m_edge[3].v = v4; + m_edge[3].f = f4; + } + }; + friend std::ostream & operator<< (std::ostream &, const GeoPolyhedron::GeoFacet & facet); + int m_nvert, m_nface; GeoTrf::Vector3D *m_pV; GeoFacet *m_pF; diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoSerialTransformer.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoSerialTransformer.h index 0e6fc9be1a6f9be5aee72ea7d42b83e59ea06ca0..ffd4d146c709249a53393e6c6f309086a18cb482 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoSerialTransformer.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoSerialTransformer.h @@ -16,6 +16,7 @@ #include "GeoModelKernel/GeoVPhysVol.h" #include "GeoModelKernel/GeoXF.h" +#include <memory> class GeoSerialTransformer : public GeoGraphNode { public: @@ -25,42 +26,38 @@ class GeoSerialTransformer : public GeoGraphNode virtual void exec (GeoNodeAction *action) const; // Returns the transformation field itself. - const GeoXF::Function * getFunction () const; + const GeoXF::Function * getFunction () const{ + return m_function.get(); + } // Returns the volume: - PVConstLink getVolume () const - { + PVConstLink getVolume () const { return m_physVol; } // Returns the number of copies: - unsigned int getNCopies () const - { - return m_nCopies; + unsigned int getNCopies () const { + return m_nCopies; } // Returns the transformation to the ith copy: - GeoTrf::Transform3D getTransform (int i) const - { + GeoTrf::Transform3D getTransform (int i) const { return (*m_function) (i); } protected: - virtual ~GeoSerialTransformer(); + virtual ~GeoSerialTransformer() = default; private: - GeoSerialTransformer(const GeoSerialTransformer &right); - GeoSerialTransformer & operator=(const GeoSerialTransformer &right); - // Number of copies of a physical volume to generate. - unsigned int m_nCopies; + unsigned int m_nCopies{0}; // Recipe for the transformation; specifically, a // Transform-valued m_function of a single variable. - const GeoXF::Function *m_function; + std::unique_ptr<const GeoXF::Function> m_function{}; // The physical volume to be multiply placed. - const GeoVPhysVol *m_physVol; + GeoIntrusivePtr<const GeoVPhysVol> m_physVol{}; }; #endif diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoShape.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoShape.h index 8241e30b78610c63b8d066296dfdb009f0bfe93c..493ef70461396707ac473e186ac66c912a1695e3 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoShape.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoShape.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #ifndef GEOMODELKERNEL_GEOSHAPE_H @@ -16,19 +16,19 @@ * if (myShape->typeId()==GeoBox::classTypeId()) { * ..... * } - * This avoids the need for dynamic casting with these - * classes. + * This avoids the need for dynamic casting with these + * classes. * - * Also noteworthy: Shapes are allocated on the heap and - * deleted automatically when their reference count falls - * to zero. + * Also noteworthy: Shapes are allocated on the heap and + * deleted automatically when their reference count falls + * to zero. */ #include "GeoModelKernel/RCBase.h" #include <GeoModelKernel/GeoDefinitions.h> #include <string> -typedef unsigned int ShapeType; +using ShapeType = unsigned int; class GeoShapeIntersection; class GeoShapeUnion; class GeoShapeSubtraction; @@ -38,39 +38,49 @@ class GeoShapeAction; class GeoShape : public RCBase { public: - // Constructor for shape. Must provide the name, a string to identify this shape. - GeoShape (); + // Constructor for shape. Must provide the name, a string to identify this shape. + GeoShape () = default; - // Returns the volume of the shape, for mass inventory - virtual double volume () const = 0; + // Returns the volume of the shape, for mass inventory. + virtual double volume () const; - // Boolean OR operation for shapes + // Returns the bonding box of the shape. + virtual void extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const = 0; + + // Returns true if the shape contains the point, false otherwise. + virtual bool contains (double x, double y, double z) const = 0; + + // Boolean OR operation for shapes. const GeoShapeUnion & add (const GeoShape& shape) const; - - // Subtraction operation for shapes. + + // Subtraction operation for shapes. const GeoShapeSubtraction & subtract (const GeoShape& shape) const; - - // Intersection of shapes. + + // Intersection of shapes. const GeoShapeIntersection & intersect (const GeoShape& shape) const; - - // Shift shapes, for boolean operations. + + // Shift shapes, for boolean operations. const GeoShapeShift & operator << (const GeoTrf::Transform3D &shift) const; - - // Returns the shape type, as a string. + + // Returns the shape type, as a string. virtual const std::string & type () const = 0; - - // Returns the shape type, as an coded integer. + + // Returns the shape type, as an coded integer. virtual ShapeType typeID () const = 0; - - // Executes a GeoShapeAction + + // Executes a GeoShapeAction virtual void exec (GeoShapeAction *action) const = 0; - + protected: - virtual ~GeoShape(); + virtual ~GeoShape() = default; + + // Returns the bounding box of the specified disk. This method is used + // for calculation of the extend of a tube, cone, polycone, torus. + static void diskExtent(double rmin, double rmax, double sphi, double dphi, + double& xmin, double& ymin, double& xmax, double& ymax); + - private: - GeoShape(const GeoShape &right); - GeoShape & operator=(const GeoShape &right); }; diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoShapeIntersection.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoShapeIntersection.h index f01bb3dcec726b0a70bca5409134c8f7dab68173..029b7ce78a4e060d6261fd74c4dc9da8e876fc58 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoShapeIntersection.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoShapeIntersection.h @@ -1,80 +1,86 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #ifndef GEOMODELKERNEL_GEOSHAPEINTERSECTION_H #define GEOMODELKERNEL_GEOSHAPEINTERSECTION_H #include "GeoModelKernel/GeoShape.h" - +#include "GeoModelKernel/GeoIntrusivePtr.h" #ifndef _GeoShapePersistification_On_ class Persistifier; #endif - class GeoShapeIntersection : public GeoShape { public: - - - - // Constructor taking two shape operands. + // Constructor taking two shape operands GeoShapeIntersection (const GeoShape* A, const GeoShape* B); - // Returns the volume of the shape, for mass inventory + // Returns the volume of the shape, for mass inventory virtual double volume () const; - // Returns the AND shape type, as a string. - virtual const std::string & type () const; + // Returns the bonding box of the shape + virtual void extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const; - // Returns the AND shape type, as a coded integer. - virtual ShapeType typeID () const; + // Returns true if the shape contains the point, false otherwise + virtual bool contains (double x, double y, double z) const; - // Returns the first operand being ANDed - const GeoShape* getOpA () const; + // Returns the AND shape type, as a string. + virtual const std::string & type () const { + return getClassType(); + } - // Returns the second operand being ANDed. - const GeoShape* getOpB () const; + // Returns the AND shape type, as a coded integer. + virtual ShapeType typeID () const { + return getClassTypeID(); + } - // Executes a GeoShapeAction + // Returns the first operand being ANDed + const GeoShape* getOpA () const { + return m_opA; + } + + // Returns the second operand being ANDed. + const GeoShape* getOpB () const { + return m_opB; + } + + // Executes a GeoShapeAction virtual void exec (GeoShapeAction *action) const; - // For type identification. - static const std::string& getClassType (); + // For type identification. + static const std::string& getClassType() { + return s_classType; + } - // For type identification. - static ShapeType getClassTypeID (); + static ShapeType getClassTypeID() { + return s_classTypeID; + } protected: - virtual ~GeoShapeIntersection(); + virtual ~GeoShapeIntersection() = default; + - private: - GeoShapeIntersection(const GeoShapeIntersection &right); - GeoShapeIntersection & operator=(const GeoShapeIntersection &right); + // The first shape operand in the AND operation. + GeoIntrusivePtr<const GeoShape> m_opA{}; - // The first shape operand in the AND operation. - const GeoShape* m_opA; + // The second shape operand in the AND operation. + GeoIntrusivePtr<const GeoShape> m_opB{}; - // The second shape operand in the AND operation. - const GeoShape* m_opB; + // Cached volume + mutable std::atomic<double> fVolume{-1}; static const std::string s_classType; static const ShapeType s_classTypeID; // For I/O only! - GeoShapeIntersection(){} + GeoShapeIntersection() = default; friend Persistifier; }; -inline const std::string& GeoShapeIntersection::getClassType () -{ - return s_classType; -} -inline ShapeType GeoShapeIntersection::getClassTypeID () -{ - return s_classTypeID; -} #endif diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoShapeShift.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoShapeShift.h index 870bf304d9ec48be8e690ab8de7cb4e2338bde4b..1274a5144dfe4cb55e8a41ce25c3e0b09af199b7 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoShapeShift.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoShapeShift.h @@ -1,11 +1,12 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #ifndef GEOMODELKERNEL_GEOSHAPESHIFT_H #define GEOMODELKERNEL_GEOSHAPESHIFT_H #include "GeoModelKernel/GeoShape.h" +#include "GeoModelKernel/GeoIntrusivePtr.h" #include "GeoModelKernel/GeoDefinitions.h" @@ -14,65 +15,75 @@ #endif -class GeoShapeShift : public GeoShape -{ +class GeoShapeShift : public GeoShape { public: + // Constructor GeoShapeShift (const GeoShape* A, const GeoTrf::Transform3D &X); - // Returns the volume of the shape, for mass inventory - virtual double volume () const; + // Returns the volume of the shape, for mass inventory + virtual double volume () const { + return m_op->volume(); + } - // Returns the OR shape type, as a string. - virtual const std::string & type () const; + // Returns the bonding box of the shape + virtual void extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const; - // Returns the OR shape type, as a coded integer. - virtual ShapeType typeID () const; + // Returns true if the shape contains the point, false otherwise + virtual bool contains (double x, double y, double z) const; - // Returns the first operand being ORed - const GeoShape* getOp () const; + // Returns the OR shape type, as a string. + virtual const std::string & type() const { + return getClassType(); + } - // Returns the shift of this shape. - const GeoTrf::Transform3D & getX () const; + // Returns the OR shape type, as a coded integer. + virtual ShapeType typeID () const { + return getClassTypeID(); + } - // Executes a GeoShapeAction + // Returns the first operand being ORed + const GeoShape* getOp() const { + return m_op; + } + + // Returns the shift of this shape. + const GeoTrf::Transform3D & getX () const { + return m_shift; + } + + // Executes a GeoShapeAction virtual void exec (GeoShapeAction *action) const; - // For type identification. - static const std::string& getClassType (); + - // For type identification. - static ShapeType getClassTypeID (); + static ShapeType getClassTypeID () { + return s_classTypeID; + } - protected: - virtual ~GeoShapeShift(); - private: - GeoShapeShift(const GeoShapeShift &right); - GeoShapeShift & operator=(const GeoShapeShift &right); + // For type identification. + static const std::string& getClassType () { + return s_classType; + } - // The shape operand in the NOT operation. - const GeoShape* m_op; + protected: + virtual ~GeoShapeShift() = default; - // Gives the amount by which the volume is shifted. - GeoTrf::Transform3D m_shift; + private: + // The shape operand in the NOT operation. + GeoIntrusivePtr<const GeoShape> m_op{}; - static const std::string s_classType; - static const ShapeType s_classTypeID; + // Gives the amount by which the volume is shifted. + GeoTrf::Transform3D m_shift{GeoTrf::Transform3D::Identity()}; - // For I/O only! - GeoShapeShift(){} - friend Persistifier; + static const std::string s_classType; + static const ShapeType s_classTypeID; + /// For I/O only! + GeoShapeShift() = default; + friend Persistifier; }; -inline const std::string& GeoShapeShift::getClassType () -{ - return s_classType; -} - -inline ShapeType GeoShapeShift::getClassTypeID () -{ - return s_classTypeID; -} #endif diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoShapeSubtraction.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoShapeSubtraction.h index 864112011a1f222c3a186d9f8ab34435875b75d7..2ab3e08e468fc5ff4461bf762152e6f757a57053 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoShapeSubtraction.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoShapeSubtraction.h @@ -1,11 +1,12 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #ifndef GEOMODELKERNEL_GEOSHAPESUBTRACTION_H #define GEOMODELKERNEL_GEOSHAPESUBTRACTION_H #include "GeoModelKernel/GeoShape.h" +#include "GeoModelKernel/GeoIntrusivePtr.h" #ifndef _GeoShapePersistification_On_ @@ -13,65 +14,76 @@ #endif -class GeoShapeSubtraction : public GeoShape -{ +class GeoShapeSubtraction : public GeoShape { public: + // Constructor taking two shape operands GeoShapeSubtraction (const GeoShape* A, const GeoShape* B); - // Returns the volume of the shape, for mass inventory + // Returns the volume of the shape, for mass inventory virtual double volume () const; - // Returns the NOT shape type, as a string. - virtual const std::string & type () const; + // Returns the bonding box of the shape + virtual void extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const; - // Returns the NOT shape type, as a coded integer. - virtual ShapeType typeID () const; + // Returns true if the shape contains the point, false otherwise + virtual bool contains (double x, double y, double z) const; - // Returns the first operand in the subtraction - const GeoShape* getOpA () const; + // Returns the NOT shape type, as a string. + virtual const std::string & type () const{ + return getClassType(); + } - // Returns the second operand in the subtraction - const GeoShape* getOpB () const; + // Returns the NOT shape type, as a coded integer. + virtual ShapeType typeID () const{ + return getClassTypeID(); + } - // Executes a GeoShapeAction + // Returns the first operand in the subtraction + const GeoShape* getOpA () const{ + return m_opA; + } + + // Returns the second operand in the subtraction + const GeoShape* getOpB () const{ + return m_opB; + } + + // Executes a GeoShapeAction virtual void exec (GeoShapeAction *action) const; - // For type identification. - static const std::string& getClassType (); + // For type identification. + static const std::string& getClassType() { + return s_classType; + } - // For type identification. - static ShapeType getClassTypeID (); + // For type identification. + static ShapeType getClassTypeID() { + return s_classTypeID; + } protected: - virtual ~GeoShapeSubtraction(); + virtual ~GeoShapeSubtraction() = default; private: - GeoShapeSubtraction(const GeoShapeSubtraction &right); - GeoShapeSubtraction & operator=(const GeoShapeSubtraction &right); + + // The first shape operand in the Subtraction operation + GeoIntrusivePtr<const GeoShape> m_opA{nullptr}; - // The shape operand in the Subtraction operation - const GeoShape* m_opA; + // The second shape operand in the Subtraction operation + GeoIntrusivePtr<const GeoShape> m_opB{nullptr}; - // The shape operand in the Subtraction operation - const GeoShape* m_opB; + // Cached volume + mutable std::atomic<double> fVolume{-1.}; static const std::string s_classType; static const ShapeType s_classTypeID; // For I/O only! - GeoShapeSubtraction(){} + GeoShapeSubtraction() = default; friend Persistifier; }; -inline const std::string& GeoShapeSubtraction::getClassType () -{ - return s_classType; -} - -inline ShapeType GeoShapeSubtraction::getClassTypeID () -{ - return s_classTypeID; -} #endif diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoShapeUnion.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoShapeUnion.h index 0661ffcda6d0bf4011b73202cf0da2193d18132a..b712b180a3a48e8ccc474b7e267ec3c660ffb9e4 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoShapeUnion.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoShapeUnion.h @@ -1,11 +1,12 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #ifndef GEOMODELKERNEL_GEOSHAPEUNION_H #define GEOMODELKERNEL_GEOSHAPEUNION_H #include "GeoModelKernel/GeoShape.h" +#include "GeoModelKernel/GeoIntrusivePtr.h" #ifndef _GeoShapePersistification_On_ class Persistifier; @@ -14,62 +15,76 @@ class GeoShapeUnion : public GeoShape { public: + // Constructor taking two shape operands GeoShapeUnion (const GeoShape* A, const GeoShape* B); - // Returns the volume of the shape, for mass inventory + // Returns the volume of the shape, for mass inventory virtual double volume () const; - // Returns the OR shape type, as a string. - virtual const std::string & type () const; + // Returns the bonding box of the shape + virtual void extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const; - // Returns the OR shape type, as a coded integer. - virtual ShapeType typeID () const; + // Returns true if the shape contains the point, false otherwise + virtual bool contains (double x, double y, double z) const; - // Returns the first operand being ORed - const GeoShape* getOpA () const; + + + // Returns the OR shape type, as a string. + virtual const std::string & type() const{ + return getClassType(); + } - // Returns the second operand being ORed. - const GeoShape* getOpB () const; + // Returns the OR shape type, as a coded integer. + virtual ShapeType typeID() const { + return getClassTypeID(); + } - // Executes a GeoShapeAction + // Returns the first operand being ORed + const GeoShape* getOpA() const { + return m_opA; + } + + // Returns the second operand being ORed. + const GeoShape* getOpB() const{ + return m_opB; + } + + // Executes a GeoShapeAction virtual void exec (GeoShapeAction *action) const; - // For type identification. - static const std::string& getClassType (); + // For type identification. + static const std::string& getClassType() { + return s_classType; + } - // For type identification. - static ShapeType getClassTypeID (); + // For type identification. + static ShapeType getClassTypeID() { + return s_classTypeID; + } protected: - virtual ~GeoShapeUnion(); + virtual ~GeoShapeUnion() = default; private: - GeoShapeUnion(const GeoShapeUnion &right); - GeoShapeUnion & operator=(const GeoShapeUnion &right); - // The first shape operand in the OR operation. - const GeoShape* m_opA; - // The second shape operand in the OR operation. - const GeoShape* m_opB; + // The first shape operand in the OR operation + GeoIntrusivePtr<const GeoShape> m_opA{}; + + // The second shape operand in the OR operation + GeoIntrusivePtr<const GeoShape> m_opB{}; + + // Cached volume + mutable std::atomic<double> fVolume{-1.}; static const std::string s_classType; static const ShapeType s_classTypeID; // For I/O only! - GeoShapeUnion(){} + GeoShapeUnion() = default; friend Persistifier; }; -inline const std::string& GeoShapeUnion::getClassType () -{ - return s_classType; -} - -inline ShapeType GeoShapeUnion::getClassTypeID () -{ - return s_classTypeID; -} - #endif diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoSimplePolygonBrep.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoSimplePolygonBrep.h index 288a47ddd6c4bcb072542484eced7c403ffcba65..6a14880915563d497d7831b12989ec8d41c4ee7f 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoSimplePolygonBrep.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoSimplePolygonBrep.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #ifndef GEOMODELKERNEL_GEOSIMPLEPOLYGONBREP_H @@ -11,7 +11,7 @@ * @brief This shape represents a BREP solid consisting * of two equivalent polygonial faces perpendicular to Z axis. * The polygones are described by array of (x,y) vertices, - * The solid is considered valid if the number of polygon vertices >=3 + * The solid is considered valid if the number of polygon vertices >=3 * * Constructor parameter is a half length along Z axis */ @@ -19,80 +19,85 @@ #include <vector> #include "GeoModelKernel/GeoShape.h" - -class GeoSimplePolygonBrep : public GeoShape -{ +class GeoSimplePolygonBrep : public GeoShape { public: + // Constructor for the BREP. Note that the constructor + // does not fully build this object. The BREP is not valid + // until at least three vertices have been added. GeoSimplePolygonBrep(double dz); + // Returns the volume of the shape, for mass inventory virtual double volume() const; - virtual const std::string& type() const; - virtual ShapeType typeID() const; + // Returns the bonding box of the shape + virtual void extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const; - void addVertex(double XVertex, double YVertex); - unsigned int getNVertices() const; + // Returns true if the shape contains the point, false otherwise. + virtual bool contains (double x, double y, double z) const; + + // Returns the BREP shape type, as a string + virtual const std::string& type() const { + return getClassType(); + } - bool isValid () const; + // Returns the BREP shape type, as a coded integer + virtual ShapeType typeID() const{ + return getClassTypeID(); + } - const double & getXVertex(unsigned int i) const; - const double & getYVertex(unsigned int i) const; + // For type identification + static const std::string& getClassType() { + return s_classType; + } + // For type identification + static ShapeType getClassTypeID() { + return s_classTypeID; + } + + // Executes a GeoShapeAction virtual void exec(GeoShapeAction *action) const; - static const std::string& getClassType(); - static ShapeType getClassTypeID(); + // Add another vertex to the polygon. A minimum of three + // vertices are required to create a valid solid. + void addVertex(double XVertex, double YVertex); + + // Returns the number of vertices in the polygon + unsigned int getNVertices() const { + return m_xVertices.size(); + } - const double& getDZ() const; + // True if the polygon has at least three vertices, false otherwise + bool isValid () const { + return getNVertices()>=3; + } + + // Returns X coordinate of the specified vertex + double getXVertex(unsigned int i) const { + return m_xVertices.at(i); + } + + // Returns Y coordinate of the specified vertex + double getYVertex(unsigned int i) const { + return m_yVertices.at(i); + } + + // Half-length along Z axis + double getDZ() const { + return m_dZ; + } protected: - virtual ~GeoSimplePolygonBrep(); + virtual ~GeoSimplePolygonBrep() = default; private: - GeoSimplePolygonBrep(const GeoSimplePolygonBrep &right); - GeoSimplePolygonBrep & operator=(const GeoSimplePolygonBrep &right); - static const std::string s_classType; static const ShapeType s_classTypeID; - double m_dZ; - std::vector<double> m_xVertices; - std::vector<double> m_yVertices; + double m_dZ{0.}; + std::vector<double> m_xVertices{}; + std::vector<double> m_yVertices{}; }; -inline unsigned int GeoSimplePolygonBrep::getNVertices() const -{ - return m_xVertices.size(); -} - -inline bool GeoSimplePolygonBrep::isValid() const -{ - return getNVertices()>=3; -} - -inline const double& GeoSimplePolygonBrep::getXVertex(unsigned int i) const -{ - return m_xVertices[i]; -} - -inline const double& GeoSimplePolygonBrep::getYVertex(unsigned int i) const -{ - return m_yVertices[i]; -} - -inline const std::string& GeoSimplePolygonBrep::getClassType() -{ - return s_classType; -} - -inline ShapeType GeoSimplePolygonBrep::getClassTypeID() -{ - return s_classTypeID; -} - -inline const double& GeoSimplePolygonBrep::getDZ() const -{ - return m_dZ; -} - #endif diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTessellatedSolid.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTessellatedSolid.h index 0a8fa8b69fbf5fd08805cc94bfdab35ba133325c..72850483cac4cb48b72324f9a6861ade68568aaf 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTessellatedSolid.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTessellatedSolid.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #ifndef GEOMODELKERNEL_GEOTESSELLATEDSOLID_H @@ -7,40 +7,66 @@ #include "GeoModelKernel/GeoShape.h" #include "GeoModelKernel/GeoFacet.h" +#include "GeoModelKernel/GeoIntrusivePtr.h" -class GeoTessellatedSolid : public GeoShape -{ +class GeoTessellatedSolid : public GeoShape { public: + // Constructor for the TESSELLATED SOLID. Note that the constructor + // does not fully build this object. The TESSELLATED SOLID is not valid + // until at least four facets have been added. GeoTessellatedSolid(); + // Returns the volume of the shape, for mass inventory virtual double volume() const; - virtual const std::string& type() const; - virtual ShapeType typeID() const; + // Returns the bonding box of the shape + virtual void extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const; + + // Returns true if the shape contains the point, false otherwise. + virtual bool contains (double x, double y, double z) const; + + // Returns the TESSELLATED SOLID shape type, as a string + virtual const std::string& type() const{ + return getClassType(); + } + // Returns the TESSELLATED SOLID shape type, as a coded integer + virtual ShapeType typeID() const { + return getClassTypeID(); + } + + // For type identification static const std::string& getClassType(); + + // For type identification static ShapeType getClassTypeID(); - virtual void exec(GeoShapeAction *action) const; + // Executes a GeoShapeAction + virtual void exec(GeoShapeAction* action) const; - void addFacet(GeoFacet*); - GeoFacet* getFacet(size_t) const; + // Add another facet to the tessellated solid. A minimum of four + // facets are required to create a valid tesselated solid. + void addFacet(GeoFacet* facet); + + // Returns specified facet + GeoFacet* getFacet(size_t index) const; + + // Returns the number of facets size_t getNumberOfFacets() const; - //! True if the polygon has at least two facets. False otherwise. - // bool isValid () const; // TODO: implement, like, e.g., in GeoPgon + // True if the tessellated solid has at least four facets (tetrahedron), + // false otherwise. + bool isValid () const; protected: - virtual ~GeoTessellatedSolid(); + virtual ~GeoTessellatedSolid() = default; private: - GeoTessellatedSolid(const GeoTessellatedSolid &right); - GeoTessellatedSolid& operator=(const GeoTessellatedSolid &right); - static const std::string s_classType; static const ShapeType s_classTypeID; - std::vector<GeoFacet*> m_facets; + std::vector<GeoIntrusivePtr<GeoFacet>> m_facets; }; inline const std::string& GeoTessellatedSolid::getClassType() @@ -53,10 +79,9 @@ inline ShapeType GeoTessellatedSolid::getClassTypeID() return s_classTypeID; } -// TODO: implement, like, e.g., in GeoPgon -//inline bool GeoPgon::isValid () const -//{ -// return m_zPlane.size () >= 2; -//} +inline bool GeoTessellatedSolid::isValid () const +{ + return m_facets.size () >= 4; +} #endif diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTorus.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTorus.h index 54c4747d7258edf7af781ce440a8abf1a27d98d3..cbbe6fd2b0f324d60094ff0e3b2ca56cedf1ff8a 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTorus.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTorus.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #ifndef GEOMODELKERNEL_GEOTORUS_H @@ -8,78 +8,82 @@ #include "GeoModelKernel/GeoShape.h" -class GeoTorus : public GeoShape -{ +class GeoTorus : public GeoShape { public: GeoTorus (double Rmin, double Rmax, double Rtor, double SPhi, double DPhi); + // Returns the volume of the shape, for mass inventory. virtual double volume () const; - virtual const std::string & type () const; - virtual ShapeType typeID () const; + // Returns the bonding box of the shape. + virtual void extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const; - static const std::string& getClassType (); - static ShapeType getClassTypeID (); + // Returns true if the shape contains the point, false otherwise. + virtual bool contains (double x, double y, double z) const; + // Returns the TORUS shape type, as a string. + virtual const std::string & type () const { + return getClassType(); + } + + // Returns the TORUS shape type, as a coded integer. + virtual ShapeType typeID () const { + return getClassTypeID(); + } + + // Executes a GeoShapeAction. virtual void exec (GeoShapeAction *action) const; - const double& getRMin () const; - const double& getRMax () const; - const double& getRTor () const; - const double& getSPhi () const; - const double& getDPhi () const; + // For type identification. + static const std::string& getClassType () { + return s_classType; + } + + // For type identification. + static ShapeType getClassTypeID () { + return s_classTypeID; + } + + // Inner radius. + double getRMin () const{ + return m_rMin; + } + + // Outer radius. + double getRMax () const { + return m_rMax; + } + + // Radius of the torus. + double getRTor () const { + return m_rTor; + } + + // Starting angle of the segment in radians. + double getSPhi () const { + return m_sPhi; + } + + // Delta angle of the segment in radians. + double getDPhi () const { + return m_dPhi; + } protected: - virtual ~GeoTorus(); + virtual ~GeoTorus() = default; private: - GeoTorus(const GeoTorus &right); - GeoTorus & operator=(const GeoTorus &right); + static const std::string s_classType; static const ShapeType s_classTypeID; - double m_rMin; - double m_rMax; - double m_rTor; - double m_sPhi; - double m_dPhi; + double m_rMin{0.}; + double m_rMax{0.}; + double m_rTor{0.}; + double m_sPhi{0.}; + double m_dPhi{0.}; }; -inline const std::string& GeoTorus::getClassType () -{ - return s_classType; -} - -inline ShapeType GeoTorus::getClassTypeID () -{ - return s_classTypeID; -} - -inline const double& GeoTorus::getRMin () const -{ - return m_rMin; -} - -inline const double& GeoTorus::getRMax () const -{ - return m_rMax; -} - -inline const double& GeoTorus::getRTor () const -{ - return m_rTor; -} - -inline const double& GeoTorus::getSPhi () const -{ - return m_sPhi; -} - -inline const double& GeoTorus::getDPhi () const -{ - return m_dPhi; -} - - #endif diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTransform.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTransform.h index 032e926590a1104dbb8b7dadca7dc29b5adb0955..d036550654e5b20853f0539c85f879397e16d60c 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTransform.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTransform.h @@ -19,29 +19,26 @@ class GeoVAlignmentStore; -class GeoTransform : public GeoGraphNode -{ +class GeoTransform : public GeoGraphNode { public: - GeoTransform(const GeoTrf::Transform3D& transform); + GeoTransform(const GeoTrf::Transform3D& transform); - GeoTransform(const GeoTransform &right) = delete; - GeoTransform & operator=(const GeoTransform &right) = delete; - /// Gets the total transformation. - virtual GeoTrf::Transform3D getTransform(const GeoVAlignmentStore* store=nullptr) const; + /// Gets the total transformation. + virtual GeoTrf::Transform3D getTransform(const GeoVAlignmentStore* store=nullptr) const; - /// Gets the default transformation (no alignment correction) - GeoTrf::Transform3D getDefTransform(const GeoVAlignmentStore* store=nullptr) const; + /// Gets the default transformation (no alignment correction) + const GeoTrf::Transform3D& getDefTransform(const GeoVAlignmentStore* store=nullptr) const; - /// Executes a GeoNodeAction. - virtual void exec(GeoNodeAction *action) const override final; + /// Executes a GeoNodeAction. + virtual void exec(GeoNodeAction *action) const override final; protected: - virtual ~GeoTransform() override; + virtual ~GeoTransform() = default; private: - // The Euclidean (Rigid Body) transform. - GeoTrf::Transform3D m_transform; + // The Euclidean (Rigid Body) transform. + GeoTrf::Transform3D m_transform{GeoTrf::Transform3D::Identity()}; }; #endif diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTrap.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTrap.h index 2f47b45bbed0140cfa7829d7be9dd12f640c5b20..3726befa69196c3789560ce0ae6d593a6bab7081 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTrap.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTrap.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration */ #ifndef GEOMODELKERNEL_GEOTRAP_H @@ -18,142 +18,91 @@ class GeoTrap : public GeoShape public: GeoTrap (double ZHalfLength, double Theta, double Phi, double Dydzn, double Dxdyndzn, double Dxdypdzn, double Angleydzn, double Dydzp, double Dxdyndzp, double Dxdypdzp, double Angleydzp); - // Returns the volume of the shape, for mass inventory + // Returns the volume of the shape, for mass inventory. virtual double volume () const; - - // Returns the TRAP shape type, as a string. - virtual const std::string & type () const; - - // Returns the TRAP shape type, as a coded integer. - virtual ShapeType typeID () const; - - // Executes a GeoShapeAction + + // Returns the bonding box of the shape. + virtual void extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const; + + // Returns true if the shape contains the point, false otherwise. + virtual bool contains (double x, double y, double z) const; + + // Returns the TRAP shape type, as a string. + virtual const std::string & type () const { + return getClassType(); + } + + // Returns the TRAP shape type, as a coded integer. + virtual ShapeType typeID() const { + return getClassTypeID(); + } + + // Executes a GeoShapeAction. virtual void exec (GeoShapeAction *action) const; - - // For type identification. - static const std::string& getClassType (); - - // For type identification. - static ShapeType getClassTypeID (); - - // Z half length. - const double& getZHalfLength () const; - - // Polar (theta) angle. - const double& getTheta () const; - - // Azimuthal (phi) angle. - const double& getPhi () const; - - // Y half length at -z. - const double& getDydzn () const; - - // X half length at -z, -y. - const double& getDxdyndzn () const; - - // X half length at -z, +y - const double& getDxdypdzn () const; - - const double& getAngleydzn () const; - - // Y half length at +z. - const double& getDydzp () const; - - // X half length at +z, -y - const double& getDxdyndzp () const; - - // X half length at +z, +y - const double& getDxdypdzp () const; - - const double& getAngleydzp () const; - - protected: - virtual ~GeoTrap(); - private: - GeoTrap(const GeoTrap &right); - GeoTrap & operator=(const GeoTrap &right); + // For type identification. + static const std::string& getClassType () { + return s_classType; + } - static const std::string s_classType; - static const ShapeType s_classTypeID; + // For type identification. + static ShapeType getClassTypeID() { + return s_classTypeID; + } - double m_zHalfLength; - double m_theta; - double m_phi; - double m_dydzn; - double m_dxdyndzn; - double m_dxdypdzn; - double m_angleydzn; - double m_dydzp; - double m_dxdyndzp; - double m_dxdypdzp; - double m_angleydzp; + // Z half length. + double getZHalfLength () const { return m_zHalfLength; } -}; + // Polar (theta) angle. + double getTheta () const { return m_theta; } + // Azimuthal (phi) angle. + double getPhi () const { return m_phi; } -inline const std::string& GeoTrap::getClassType () -{ - return s_classType; -} + // Y half length at -z. + double getDydzn () const { return m_dydzn; } -inline ShapeType GeoTrap::getClassTypeID () -{ - return s_classTypeID; -} + // X half length at -z, -y. + double getDxdyndzn () const { return m_dxdyndzn; } -inline const double& GeoTrap::getZHalfLength () const -{ - return m_zHalfLength; -} + // X half length at -z, +y. + double getDxdypdzn () const { return m_dxdypdzn; } + + double getAngleydzn () const { return m_angleydzn; } -inline const double& GeoTrap::getTheta () const -{ - return m_theta; -} + // Y half length at +z. + double getDydzp () const { return m_dydzp; } -inline const double& GeoTrap::getPhi () const -{ - return m_phi; -} + // X half length at +z, -y. + double getDxdyndzp () const { return m_dxdyndzp; } -inline const double& GeoTrap::getDydzn () const -{ - return m_dydzn; -} + // X half length at +z, +y. + double getDxdypdzp () const { return m_dxdypdzp; } + + double getAngleydzp () const { return m_angleydzp; } -inline const double& GeoTrap::getDxdyndzn () const -{ - return m_dxdyndzn; -} + protected: + virtual ~GeoTrap() = default; -inline const double& GeoTrap::getDxdypdzn () const -{ - return m_dxdypdzn; -} + private: -inline const double& GeoTrap::getAngleydzn () const -{ - return m_angleydzn; -} -inline const double& GeoTrap::getDydzp () const -{ - return m_dydzp; -} + static const std::string s_classType; + static const ShapeType s_classTypeID; -inline const double& GeoTrap::getDxdyndzp () const -{ - return m_dxdyndzp; -} + double m_zHalfLength{0.}; + double m_theta{0.}; + double m_phi{0.}; + double m_dydzn{0.}; + double m_dxdyndzn{0.}; + double m_dxdypdzn{0.}; + double m_angleydzn{0.}; + double m_dydzp{0.}; + double m_dxdyndzp{0.}; + double m_dxdypdzp{0.}; + double m_angleydzp{0.}; -inline const double& GeoTrap::getDxdypdzp () const -{ - return m_dxdypdzp; -} +}; -inline const double& GeoTrap::getAngleydzp () const -{ - return m_angleydzp; -} #endif diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTrd.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTrd.h index 6bfa31c4ec152729652fdba21ea32bea9de1ebb4..48b6759e53088042f336edbabbd3ac93f67d548a 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTrd.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTrd.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #ifndef GEOMODELKERNEL_GEOTRD_H @@ -12,90 +12,68 @@ class GeoTrd : public GeoShape public: GeoTrd (double XHalfLength1, double XHalfLength2, double YHalfLength1, double YHalfLength2, double ZHalfLength); - // Returns the volume of the shape, for mass inventory + // Returns the volume of the shape, for mass inventory. virtual double volume () const; - - // Returns the TRD shape type, as a string. - virtual const std::string & type () const; - - // Returns the TRD shape type, as a coded integer. - virtual ShapeType typeID () const; - - // Executes a GeoShapeAction + + // Returns the bonding box of the shape. + virtual void extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const; + + // Returns true if the shape contains the point, false otherwise. + virtual bool contains (double x, double y, double z) const; + + // Returns the TRD shape type, as a string. + virtual const std::string & type () const{ + return getClassType(); + } + + // Returns the TRD shape type, as a coded integer. + virtual ShapeType typeID () const { + return getClassTypeID(); + } + + // Executes a GeoShapeAction. virtual void exec (GeoShapeAction *action) const; - - // For type identification. - static const std::string& getClassType (); - - // For type identification. - static ShapeType getClassTypeID (); - - // Half length in the x-direction at -dz. - const double& getXHalfLength1 () const; - - // Half length in the x-direction at +dz - const double& getXHalfLength2 () const; - - // Half-length in the y direction at +dz. - const double& getYHalfLength1 () const; - - // Half-length in the y direction at -dz - const double& getYHalfLength2 () const; - - // Half-length in the z direction. - const double& getZHalfLength () const; - protected: - virtual ~GeoTrd(); + // For type identification. + static const std::string& getClassType() { + return s_classType; + } - private: - GeoTrd(const GeoTrd &right); - GeoTrd & operator=(const GeoTrd &right); - - static const std::string s_classType; - static const ShapeType s_classTypeID; + // For type identification. + static ShapeType getClassTypeID(){ + return s_classTypeID; + } - double m_xHalfLength1; - double m_xHalfLength2; - double m_yHalfLength1; - double m_yHalfLength2; - double m_zHalfLength; + // Half length in the x-direction at -dz. + double getXHalfLength1 () const { return m_xHalfLength1; } -}; + // Half length in the x-direction at +dz. + double getXHalfLength2 () const { return m_xHalfLength2; } -inline const std::string& GeoTrd::getClassType () -{ - return s_classType; -} + // Half-length in the y direction at +dz. + double getYHalfLength1 () const { return m_yHalfLength1; } -inline ShapeType GeoTrd::getClassTypeID () -{ - return s_classTypeID; -} + // Half-length in the y direction at -dz. + double getYHalfLength2 () const { return m_yHalfLength2; } -inline const double& GeoTrd::getXHalfLength1 () const -{ - return m_xHalfLength1; -} + // Half-length in the z direction. + double getZHalfLength () const { return m_zHalfLength; } -inline const double& GeoTrd::getXHalfLength2 () const -{ - return m_xHalfLength2; -} + protected: + virtual ~GeoTrd() = default; -inline const double& GeoTrd::getYHalfLength1 () const -{ - return m_yHalfLength1; -} + private: -inline const double& GeoTrd::getYHalfLength2 () const -{ - return m_yHalfLength2; -} + static const std::string s_classType; + static const ShapeType s_classTypeID; -inline const double& GeoTrd::getZHalfLength () const -{ - return m_zHalfLength; -} + double m_xHalfLength1{0.}; + double m_xHalfLength2{0.}; + double m_yHalfLength1{0.}; + double m_yHalfLength2{0.}; + double m_zHalfLength{0.}; + +}; #endif diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTube.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTube.h index 4354cfd4baa437c229ee25ac76cad45709231568..f9d7e2370ab060e05bef846cb7bffd4f9645fe95 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTube.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTube.h @@ -12,37 +12,57 @@ class GeoTube : public GeoShape public: GeoTube (double RMin, double RMax, double ZHalfLength); - // Returns the volume of the shape, for mass inventory + // Returns the volume of the shape, for mass inventory. virtual double volume () const; - - // Returns the TUBE shape type, as a string. - virtual const std::string & type () const; - - // Returns the TUBE shape type, as a coded integer. - virtual ShapeType typeID () const; - - // Executes a GeoShapeAction + + // Returns the bonding box of the shape. + virtual void extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const; + + // Returns true if the shape contains the point, false otherwise. + virtual bool contains (double x, double y, double z) const; + + // Returns the TUBE shape type, as a string. + virtual const std::string & type () const{ + return getClassType(); + } + + // Returns the TUBE shape type, as a coded integer. + virtual ShapeType typeID () const{ + return getClassTypeID(); + } + // Executes a GeoShapeAction. virtual void exec (GeoShapeAction *action) const; - - // For type identification. - static const std::string& getClassType (); - - // For type identification. - static ShapeType getClassTypeID (); - - // Minimum (inner) tube radius. - const double& getRMin () const; - - // Maximum (outer) tube radius. - const double& getRMax () const; - - // Tube half-length in the z direction. - const double& getZHalfLength () const; - + + // For type identification. + static const std::string& getClassType () { + return s_classType; + } + + // For type identification. + static ShapeType getClassTypeID () { + return s_classTypeID; + } + + // Minimum (inner) tube radius. + double getRMin () const { + return m_rMin; + } + + // Maximum (outer) tube radius. + double getRMax () const { + return m_rMax; + } + + // Tube half-length in the z direction. + double getZHalfLength () const { + return m_zHalfLength; + } + protected: //## Destructor (generated) virtual ~GeoTube(); - + private: GeoTube(const GeoTube &right); GeoTube & operator=(const GeoTube &right); @@ -50,35 +70,10 @@ class GeoTube : public GeoShape static const std::string s_classType; static const ShapeType s_classTypeID; - double m_rMin; - double m_rMax; - double m_zHalfLength; + double m_rMin{0.}; + double m_rMax{0.}; + double m_zHalfLength{0.}; }; -inline const std::string& GeoTube::getClassType () -{ - return s_classType; -} - -inline ShapeType GeoTube::getClassTypeID () -{ - return s_classTypeID; -} - -inline const double& GeoTube::getRMin () const -{ - return m_rMin; -} - -inline const double& GeoTube::getRMax () const -{ - return m_rMax; -} - -inline const double& GeoTube::getZHalfLength () const -{ - return m_zHalfLength; -} - #endif diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTubs.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTubs.h index 68f8399fb5b2ed27cee402f3d3fc8520238cf1d6..79d3dbf400aa5aafb242e15b775cb2771e27a338 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTubs.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTubs.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #ifndef GEOMODELKERNEL_GEOTUBS_H @@ -12,90 +12,78 @@ class GeoTubs : public GeoShape public: GeoTubs (double RMin, double RMax, double ZHalfLength, double SPhi, double DPhi); - // Returns the volume of the shape, for mass inventory + // Returns the volume of the shape, for mass inventory. virtual double volume () const; - // Returns the TUBS shape type, as a string. - virtual const std::string & type () const; + // Returns the bonding box of the shape. + virtual void extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const; - // Returns the TUBS shape type, as a coded integer. - virtual ShapeType typeID () const; + // Returns true if the shape contains the point, false otherwise. + virtual bool contains (double x, double y, double z) const; - // Executes a GeoShapeAction - virtual void exec (GeoShapeAction *action) const; - - // For type identification. - static const std::string& getClassType (); - - // For type identification. - static ShapeType getClassTypeID (); - - // Minimum (inner) tube section radius. - const double& getRMin () const; - - // Maximum (outer) tube section radius. - const double& getRMax () const; + // Returns the TUBS shape type, as a string. + virtual const std::string & type () const { + return getClassType(); + } - // Tube section half-length in the z direction. - const double& getZHalfLength () const; + // Returns the TUBS shape type, as a coded integer. + virtual ShapeType typeID () const { + return getClassTypeID(); + } - // Starting angle of the tube section in radians. - const double& getSPhi () const; + // Executes a GeoShapeAction. + virtual void exec (GeoShapeAction *action) const; - // Delta angle of the tube section in radians. - const double& getDPhi () const; + // For type identification. + static const std::string& getClassType () { + return s_classType; + } + + // For type identification. + static ShapeType getClassTypeID () { + return s_classTypeID; + } + + // Minimum (inner) tube section radius. + double getRMin() const { + return m_rMin; + } + + // Maximum (outer) tube section radius. + double getRMax () const { + return m_rMax; + } + + // Tube section half-length in the z direction. + double getZHalfLength () const { + return m_zHalfLength; + } + + // Starting angle of the tube section in radians. + double getSPhi () const{ + return m_sPhi; + } + + // Delta angle of the tube section in radians. + double getDPhi () const { + return m_dPhi; + } protected: - virtual ~GeoTubs(); + virtual ~GeoTubs() = default; private: - GeoTubs(const GeoTubs &right); - GeoTubs & operator=(const GeoTubs &right); static const std::string s_classType; static const ShapeType s_classTypeID; - double m_rMin; - double m_rMax; - double m_zHalfLength; - double m_sPhi; - double m_dPhi; + double m_rMin{0.}; + double m_rMax{0.}; + double m_zHalfLength{0.}; + double m_sPhi{0.}; + double m_dPhi{0.}; }; -inline const std::string& GeoTubs::getClassType () -{ - return s_classType; -} - -inline ShapeType GeoTubs::getClassTypeID () -{ - return s_classTypeID; -} - -inline const double& GeoTubs::getRMin () const -{ - return m_rMin; -} - -inline const double& GeoTubs::getRMax () const -{ - return m_rMax; -} - -inline const double& GeoTubs::getZHalfLength () const -{ - return m_zHalfLength; -} - -inline const double& GeoTubs::getSPhi () const -{ - return m_sPhi; -} - -inline const double& GeoTubs::getDPhi () const -{ - return m_dPhi; -} - #endif diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTwistedTrap.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTwistedTrap.h index e88cc4665ab9bea7e634b84ee4e96ccb47ede466..e54dd5293512c7c5246a247d65e32c8a7bcfd694 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTwistedTrap.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTwistedTrap.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #ifndef GEOMODELKERNEL_GEOTWISTEDTRAP_H @@ -43,13 +43,13 @@ class GeoTwistedTrap : public GeoShape { public: - + GeoTwistedTrap(double pPhiTwist, double pDx1, // half x length at -pDz,-pDy double pDx2, // half x length at -pDz,+pDy double pDy, double pDz); - + GeoTwistedTrap(double pPhiTwist, // twist angle double pDz, // half z length double pTheta, // direction between end planes @@ -63,25 +63,40 @@ class GeoTwistedTrap : public GeoShape double pAlph // tilt angle ); - // Returns the volume of the shape, for mass inventory + // Returns the volume of the shape, for mass inventory virtual double volume () const; - - // Returns the TWISTED TRAP shape type, as a string. - virtual const std::string & type () const; - - // Returns the TWISTED TRAP shape type, as a coded integer. - virtual ShapeType typeID () const; - - // Executes a GeoShapeAction + + // Returns the bonding box of the shape. + virtual void extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const; + + // Returns true if the shape contains the point, false otherwise. + virtual bool contains (double x, double y, double z) const; + + // Returns the TWISTED TRAP shape type, as a string. + virtual const std::string & type () const { + return s_classType; + } + + // Returns the TWISTED TRAP shape type, as a coded integer. + virtual ShapeType typeID () const { + return getClassTypeID(); + } + + // Executes a GeoShapeAction virtual void exec (GeoShapeAction *action) const; - - // For type identification. - static const std::string& getClassType (); - - // For type identification. - static ShapeType getClassTypeID (); - - + + // For type identification. + static const std::string& getClassType () { + return s_classType; + } + + // For type identification. + static ShapeType getClassTypeID () { + return s_classTypeID; + } + + inline double getY1HalfLength() const { return m_dy1 ; } inline double getX1HalfLength() const { return m_dx1 ; } inline double getX2HalfLength() const { return m_dx2 ; } @@ -93,42 +108,32 @@ class GeoTwistedTrap : public GeoShape inline double getTheta() const { return m_theta ; } inline double getPhi() const { return m_phi ; } inline double getTiltAngleAlpha() const { return m_alph ; } - + protected: - virtual ~GeoTwistedTrap(); + virtual ~GeoTwistedTrap() = default; private: - GeoTwistedTrap(const GeoTwistedTrap &right); - GeoTwistedTrap & operator=(const GeoTwistedTrap &right); + static const std::string s_classType; static const ShapeType s_classTypeID; - double m_theta; - double m_phi ; - double m_dy1; - double m_dx1; - double m_dx2; - double m_dy2; - double m_dx3; - double m_dx4; - double m_dz; // Half-length along the z axis - double m_alph ; - double m_phiTwist; // twist angle ( dphi in surface equation) - - const double m_CarTolerance = 1E-9 * SYSTEM_OF_UNITS::mm; - const double m_RadTolerance = 1E-9 * SYSTEM_OF_UNITS::mm; - const double m_AngTolerance = 1E-9 * SYSTEM_OF_UNITS::rad; + double m_theta{0.}; + double m_phi{0.}; + double m_dy1{0.}; + double m_dx1{0.}; + double m_dx2{0.}; + double m_dy2{0.}; + double m_dx3{0.}; + double m_dx4{0.}; + double m_dz{0.}; // Half-length along the z axis + double m_alph{0.}; + double m_phiTwist{0.}; // twist angle ( dphi in surface equation) -}; + static constexpr double m_CarTolerance = 1E-9 * SYSTEM_OF_UNITS::mm; + static constexpr double m_RadTolerance = 1E-9 * SYSTEM_OF_UNITS::mm; + static constexpr double m_AngTolerance = 1E-9 * SYSTEM_OF_UNITS::rad; -inline const std::string& GeoTwistedTrap::getClassType () -{ - return s_classType; -} +}; -inline ShapeType GeoTwistedTrap::getClassTypeID () -{ - return s_classTypeID; -} #endif diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoUnidentifiedShape.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoUnidentifiedShape.h index 22428ec6a60b3ba189d8d73f905c1c4da247b6ce..8f021aee87077af65fcf6b5bd3f4b7e9b3bd2282 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoUnidentifiedShape.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoUnidentifiedShape.h @@ -8,7 +8,7 @@ // This class is essentially a bundle of data with no fixed format. // ASCII information can be added and retreived. It serves as a // proxy for shapes that are not part of the kernel, i.e. extender- -// class shapes. +// class shapes. // // Joe Boudreau 2020 // @@ -19,17 +19,17 @@ #include "GeoModelKernel/GeoShape.h" #include "GeoModelKernel/Query.h" #include <string> + class GeoUnidentifiedShape: public GeoShape { public: - // Constructor: GeoUnidentifiedShape(const std::string & name); - + // Constructor: GeoUnidentifiedShape(const std::string & name, const std::string & asciiData); - - // Constructor with volume: + + // Constructor with volume: GeoUnidentifiedShape(const std::string & name, const std::string & asciiData, double volume); // Returns the user-provided name of the volume (eg "MySpecialShape"); @@ -37,32 +37,39 @@ class GeoUnidentifiedShape: public GeoShape { // Returns the ascii data associated with this object (possibly empty); const std::string & asciiData() const; - + // Returns the volume of the shape, for mass inventory virtual double volume () const; - + + // Returns the bonding box of the shape + virtual void extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const; + + // Returns true if the shape contains the point, false otherwise + virtual bool contains (double x, double y, double z) const; + // Returns the shape type, as a string. virtual const std::string & type () const; - + // Returns the shape type, as an coded integer. virtual ShapeType typeID () const; - // For type identification. + // For type identification. static const std::string& getClassType (); - // For type identification., + // For type identification., static ShapeType getClassTypeID (); - - + + // Executes a GeoShapeAction virtual void exec (GeoShapeAction *action) const; - + protected: // Destructor: ~GeoUnidentifiedShape(); - + private: const std::string _name; @@ -70,7 +77,7 @@ class GeoUnidentifiedShape: public GeoShape { const Query<double> _volume; static const std::string _classType; static const ShapeType _classTypeID; - + }; inline const std::string& GeoUnidentifiedShape::getClassType () @@ -82,4 +89,5 @@ inline ShapeType GeoUnidentifiedShape::getClassTypeID () { return _classTypeID; } + #endif diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoVDetectorElement.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoVDetectorElement.h index 4bfb10d7e742e35a449201d88d9cec99b4dbf80c..cd87452a334538a8817015637cd866edd3a51a48 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoVDetectorElement.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoVDetectorElement.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #ifndef GEOMODELKERNEL_GEOVDETECTORELEMENT_H @@ -27,18 +27,18 @@ class GeoVDetectorElement { public: GeoVDetectorElement (const GeoVFullPhysVol* fullPhysVol); - virtual ~GeoVDetectorElement(); + virtual ~GeoVDetectorElement() = default; // Returns a pointer to a physical volume which is // associated with this detector element. const GeoVFullPhysVol* getMaterialGeom () const; private: - GeoVDetectorElement(const GeoVDetectorElement &right); - GeoVDetectorElement & operator=(const GeoVDetectorElement &right); + GeoVDetectorElement(const GeoVDetectorElement &right) = delete; + GeoVDetectorElement & operator=(const GeoVDetectorElement &right) = delete; private: - const GeoVFullPhysVol *m_materialGeom; + GeoIntrusivePtr<const GeoVFullPhysVol> m_materialGeom{}; }; diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoVFullPhysVol.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoVFullPhysVol.h index 04c09c66b5d1fb51921e0951b5633426881d585f..546f536d11b7c1acf25f73889f2415a9cce0031b 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoVFullPhysVol.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoVFullPhysVol.h @@ -8,6 +8,7 @@ #include "GeoModelKernel/GeoVPhysVol.h" #include "GeoModelKernel/GeoAbsPositionInfo.h" #include <mutex> +#include <memory> class GeoVAlignmentStore; @@ -17,9 +18,6 @@ class GeoVFullPhysVol : public GeoVPhysVol public: GeoVFullPhysVol(const GeoLogVol* logVol); - GeoVFullPhysVol(const GeoVFullPhysVol &right) = delete; - GeoVFullPhysVol & operator=(const GeoVFullPhysVol &right) = delete; - /// Returns the (default) absolute transform of the volume. /// 1. When store=nullptr. This is considered a "serial case" when /// the cached (default) absolute transform is kept as a data member of the @@ -44,13 +42,13 @@ class GeoVFullPhysVol : public GeoVPhysVol void clearPositionInfo() const; /// Returns the absolute name of this node. - const std::string& getAbsoluteName(); + const std::string& getAbsoluteName() const; /// Returns the identification bits. unsigned int getId() const; protected: - virtual ~GeoVFullPhysVol() override; + virtual ~GeoVFullPhysVol() = default; /// Mutex serving dual purpose: /// 1. To protect the absolute position info @@ -59,13 +57,13 @@ class GeoVFullPhysVol : public GeoVPhysVol private: /// The absolute name of this volume. - std::string m_absName; + mutable std::string m_absName{}; /// An identifier. This is locally cached in a full physical volume. - mutable Query<int> *m_id; + mutable std::unique_ptr<Query<int>> m_id{nullptr}; /// Information on the where this volume is, by default and after alignment corrections. - mutable GeoAbsPositionInfo *m_absPosInfo; + mutable std::unique_ptr<GeoAbsPositionInfo> m_absPosInfo{nullptr}; }; diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoVGeometryPlugin.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoVGeometryPlugin.h index b2c29a63682f7df1fff2227f72bf9a247da90716..ec9b5aa56b815ec6cc43daaf3b01d698260c2f11 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoVGeometryPlugin.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoVGeometryPlugin.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #ifndef GEOMODELKERNEL_GEOVGEOMETRYPLUGIN_H @@ -33,7 +33,7 @@ class GeoVGeometryPlugin //! Create the system geometry. /// Note: this is a pure virtual method, so you need to implement it in your derived plugin class - virtual void create ( GeoPhysVol* world, bool publish = false ) = 0; + virtual void create ( GeoVPhysVol* world, bool publish = false ) = 0; //! Returns the plugin's name std::string getName() { return m_pluginName; } diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoVPhysVol.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoVPhysVol.h index d90aefb16095b4354c8dd22211ee2fa88406c737..f7df474dfb3ce5d58374bff1760657e9ebfb5833 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoVPhysVol.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoVPhysVol.h @@ -1,20 +1,11 @@ /* - Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #ifndef GEOMODELKERNEL_GEOVPHYSVOL_H #define GEOMODELKERNEL_GEOVPHYSVOL_H -#include "GeoModelKernel/GeoPVLink.h" -#define SMARTLINKS -#ifdef SMARTLINKS -typedef GeoPVLink PVLink; -typedef GeoPVConstLink PVConstLink; -#else -class GeoVPhysVol; -typedef GeoVPhysVol *PVLink; -typedef const GeoVPhysVol *PVConstLink; -#endif +#include "GeoModelKernel/GeoIntrusivePtr.h" #include "GeoModelKernel/GeoDefinitions.h" #include "GeoModelKernel/Query.h" #include <string> @@ -25,17 +16,19 @@ typedef const GeoVPhysVol *PVConstLink; class GeoVolumeAction; class GeoVAlignmentStore; -class GeoVPhysVol : public GeoGraphNode -{ +class GeoVPhysVol : public GeoGraphNode { public: - GeoVPhysVol(const GeoLogVol* LogVol); + using PVLink = GeoIntrusivePtr<GeoVPhysVol>; + using PVConstLink = GeoIntrusivePtr<const GeoVPhysVol>; + + GeoVPhysVol(const GeoLogVol* LogVol); - GeoVPhysVol(const GeoVPhysVol &right) = delete; - GeoVPhysVol & operator=(const GeoVPhysVol &right) = delete; /// Returns true if the physical volume is accessed by more than one parent. /// Should check this before trusting the parent pointer. - bool isShared() const; + bool isShared() const { + return m_parentPtr == this; + } /// Returns the index of a specific daughter volume. The Query class can be used /// just like an unsigned int, but it provides and isValid() method to determine @@ -43,10 +36,14 @@ class GeoVPhysVol : public GeoGraphNode Query<unsigned int> indexOf(PVConstLink daughter) const; /// Gets the parent, if the parent is unique, and otherwise returns a nullptr pointer. - PVConstLink getParent() const; + PVConstLink getParent() const { + return PVConstLink{isShared() ? nullptr : m_parentPtr}; + } /// Returns the logical volume. - const GeoLogVol* getLogVol() const; + const GeoLogVol* getLogVol() const { + return m_logVol; + } /// Returns the number of child physical volumes. virtual unsigned int getNChildVols() const = 0; @@ -90,20 +87,21 @@ class GeoVPhysVol : public GeoGraphNode virtual void add(GeoGraphNode* graphNode) = 0; protected: - virtual ~GeoVPhysVol(); + virtual ~GeoVPhysVol() = default; private: /// If one parent ...pointer=PARENT; /// If no parent ...pointer=nullptr. /// If more than one parent ...pointer=this; - const GeoVPhysVol* m_parentPtr; + const GeoVPhysVol* m_parentPtr{nullptr}; - const GeoLogVol *m_logVol; + GeoIntrusivePtr<const GeoLogVol> m_logVol{}; }; -inline bool GeoVPhysVol::isShared () const -{ - return m_parentPtr == this; -} +using PVLink = GeoVPhysVol::PVLink; +using PVConstLink = GeoVPhysVol::PVConstLink; + +using GeoPVLink = PVLink; +using GeoPVConstLink = PVConstLink; #endif diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/RCBase.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/RCBase.h index 0dfd0b5a9ac1c235b8422a7287fb9fc133395d7f..fb1ea2a4d49497ead58d344022957b9d16ae3a6a 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/RCBase.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/RCBase.h @@ -21,30 +21,37 @@ #include <atomic> -class RCBase -{ +class RCBase { public: - RCBase(); + RCBase() = default; // Increase the reference count - void ref () const; + void ref() const noexcept { + ++m_count; + } // Decreases the reference count. When the reference count // falls to zero, the object deletes itself. - void unref () const; + void unref () const noexcept{ + if (--m_count == 0) { + delete this; + } + } // Return the reference count. - unsigned int refCount () const; + unsigned int refCount () const noexcept { + return m_count.load(); + } protected: - virtual ~RCBase(); + virtual ~RCBase() = default; private: - RCBase(const RCBase &right); - RCBase & operator=(const RCBase &right); + RCBase(const RCBase &right) = delete; + RCBase & operator=(const RCBase &right) = delete; - // The reference count - mutable std::atomic<unsigned> m_count; + // The reference count + mutable std::atomic<unsigned> m_count{0}; }; diff --git a/GeoModelCore/GeoModelKernel/src/BooleanProcessor.src b/GeoModelCore/GeoModelKernel/src/BooleanProcessor.src index 6e3cac358a63c0985eda5d47b0ff0c87b42ec903..7eb051391330e83d68be1da3bbcab784dd1d11ed 100755 --- a/GeoModelCore/GeoModelKernel/src/BooleanProcessor.src +++ b/GeoModelCore/GeoModelKernel/src/BooleanProcessor.src @@ -1797,7 +1797,7 @@ GeoPolyhedron BooleanProcessor::createPolyhedron() << std::endl; } polyhedron.m_pF[faces[i].inew] = - GeoFacet(v[0],f[0], v[1],f[1], v[2],f[2], v[3],f[3]); + GeoPolyhedron::GeoFacet(v[0],f[0], v[1],f[1], v[2],f[2], v[3],f[3]); } return polyhedron; } diff --git a/GeoModelCore/GeoModelKernel/src/GeoAbsPositionInfo.cxx b/GeoModelCore/GeoModelKernel/src/GeoAbsPositionInfo.cxx index 1768be51d9ef466cdedd9a2bc3df1d7d579778cc..f766e2013b63de495fec5784d6f407eb80a7ea34 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoAbsPositionInfo.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoAbsPositionInfo.cxx @@ -1,55 +1,31 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #include "GeoModelKernel/GeoAbsPositionInfo.h" #include "GeoModelKernel/GeoDefinitions.h" -#include <memory> -GeoAbsPositionInfo::GeoAbsPositionInfo() - : m_absTransform(nullptr), - m_defAbsTransform(nullptr) -{ +void GeoAbsPositionInfo::clearAbsTransform () { + m_absTransform.reset(); } -GeoAbsPositionInfo::~GeoAbsPositionInfo() -{ - delete m_absTransform; - delete m_defAbsTransform; -} - -void GeoAbsPositionInfo::clearAbsTransform () -{ - delete m_absTransform; - m_absTransform = nullptr; -} - -void GeoAbsPositionInfo::clearDefAbsTransform () -{ - delete m_defAbsTransform; - m_defAbsTransform = nullptr; +void GeoAbsPositionInfo::clearDefAbsTransform () { + m_defAbsTransform.reset(); } void GeoAbsPositionInfo::setAbsTransform (const GeoTrf::Transform3D & xform) { - if (m_absTransform) - { - (*m_absTransform) = xform; - } - else - { - m_absTransform = new GeoTrf::Transform3D (xform); - } + if (m_absTransform) { + (*m_absTransform) = xform; + } else { + m_absTransform = std::make_unique<GeoTrf::Transform3D> (xform); + } } -void GeoAbsPositionInfo::setDefAbsTransform (const GeoTrf::Transform3D & xform) -{ - if (m_defAbsTransform) - { +void GeoAbsPositionInfo::setDefAbsTransform (const GeoTrf::Transform3D& xform) { + if (m_defAbsTransform) { (*m_defAbsTransform) = xform; - } - else - { - m_defAbsTransform = new GeoTrf::Transform3D (xform); - } + } else { + m_defAbsTransform = std::make_unique<GeoTrf::Transform3D>(xform); + } } diff --git a/GeoModelCore/GeoModelKernel/src/GeoAccessVolAndSTAction.cxx b/GeoModelCore/GeoModelKernel/src/GeoAccessVolAndSTAction.cxx index f38708c3c9978c94371a10511839cb9ef0a8ef8c..45bee94810c8760eb1f72ed290a2781fd68e8d22 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoAccessVolAndSTAction.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoAccessVolAndSTAction.cxx @@ -8,25 +8,11 @@ #include "GeoModelKernel/GeoSerialDenominator.h" #include <string> -GeoAccessVolAndSTAction::GeoAccessVolAndSTAction(unsigned int index) - : m_volume(0) - , m_serialTransformer(0) - , m_transform(GeoTrf::Transform3D::Identity()) - , m_defTransform(GeoTrf::Transform3D::Identity()) - , m_index(index) - , m_counter(0) - , m_nameTag(0) - , m_serialDenominator(0) - , m_idTag(0) - , m_serialDenomPosition(0) -{ +GeoAccessVolAndSTAction::GeoAccessVolAndSTAction(unsigned int index): + m_index{index} { setDepthLimit(1); } -GeoAccessVolAndSTAction::~GeoAccessVolAndSTAction() -{ -} - void GeoAccessVolAndSTAction::handleTransform(const GeoTransform *xform) { m_pendingTransformList.push_back (xform); diff --git a/GeoModelCore/GeoModelKernel/src/GeoAlignableTransform.cxx b/GeoModelCore/GeoModelKernel/src/GeoAlignableTransform.cxx index b5c0a0e0b1aeb4ef280d29e0c0ec6ec1c01e6161..e5c08560f6c06140fd153d6d733af841a993ab1c 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoAlignableTransform.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoAlignableTransform.cxx @@ -9,15 +9,8 @@ #include <set> GeoAlignableTransform::GeoAlignableTransform (const GeoTrf::Transform3D& transform) - : GeoTransform(transform) - , m_delta (nullptr) -{ -} + : GeoTransform(transform){} -GeoAlignableTransform::~GeoAlignableTransform() -{ - delete m_delta; -} #if defined(FLATTEN) && defined(__GNUC__) // We compile this package with optimization, even in debug builds; otherwise, @@ -31,64 +24,57 @@ GeoTrf::Transform3D GeoAlignableTransform::getTransform(const GeoVAlignmentStore { if(store) { const GeoTrf::Transform3D* delta = store->getDelta(this); - return GeoTransform::getTransform(nullptr) * (delta==nullptr ? GeoTrf::Transform3D(GeoTrf::Transform3D::Identity()) : *delta); + return getDefTransform(store) * (!delta ? GeoTrf::Transform3D::Identity() : *delta); } - else { + else if (m_delta) { std::scoped_lock<std::mutex> guard(m_deltaMutex); - return GeoTransform::getTransform(nullptr) * (m_delta==nullptr ? GeoTrf::Transform3D(GeoTrf::Transform3D::Identity()) : *m_delta); + return getDefTransform(store) * (*m_delta); } + return getDefTransform(store); } -void GeoAlignableTransform::setDelta (const GeoTrf::Transform3D& delta, GeoVAlignmentStore* store) -{ - if(store==nullptr) { +void GeoAlignableTransform::setDelta(const GeoTrf::Transform3D& delta, GeoVAlignmentStore* store) { + if(!store) { { std::scoped_lock<std::mutex> guard(m_deltaMutex); if(m_delta && (m_delta->isApprox(delta))) return; if(m_delta) { - (*m_delta) = delta; - } - else { - m_delta = new GeoTrf::Transform3D(delta); + (*m_delta) = delta; + } else { + m_delta = std::make_unique<GeoTrf::Transform3D>(delta); } } std::set<GeoGraphNode*> uniqueParents; for(GeoGraphNode* parent : m_parentList) { - if(uniqueParents.find(parent)==uniqueParents.end()) { - GeoSelClearAbsPosAction cc(this); - parent->exec(&cc); - uniqueParents.insert(parent); + if(uniqueParents.insert(parent).second) { + GeoSelClearAbsPosAction cc(this); + parent->exec(&cc); } } - } // if(store==nullptr) - else { + } else { store->setDelta(this,delta); } } -void GeoAlignableTransform::clearDelta(GeoVAlignmentStore* store) -{ +void GeoAlignableTransform::clearDelta(GeoVAlignmentStore* store) { // Does not make sence to clear deltas inside Alignment Store if(store!=nullptr) return; { std::scoped_lock<std::mutex> guard(m_deltaMutex); - delete m_delta; - m_delta = nullptr; + m_delta.reset(); } std::set<GeoGraphNode*> uniqueParents; for(GeoGraphNode* parent : m_parentList) { - if(uniqueParents.find(parent)==uniqueParents.end()) { - GeoSelClearAbsPosAction cc(this); - parent->exec (&cc); - uniqueParents.insert(parent); + if(uniqueParents.insert(parent).second) { + GeoSelClearAbsPosAction cc(this); + parent->exec(&cc); } } } -void GeoAlignableTransform::dockTo(GeoVPhysVol* parent) -{ +void GeoAlignableTransform::dockTo(GeoVPhysVol* parent) { m_parentList.push_back (parent); } diff --git a/GeoModelCore/GeoModelKernel/src/GeoBox.cxx b/GeoModelCore/GeoModelKernel/src/GeoBox.cxx index de07cf79cc71a3431b265ece87e72d42d35c4fcd..60b44f062aa1ccb569bc53f4cbd79ba70ef1d149 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoBox.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoBox.cxx @@ -8,33 +8,34 @@ const std::string GeoBox::s_classType = "Box"; const ShapeType GeoBox::s_classTypeID = 0x10; -GeoBox::GeoBox (double XHalfLength, double YHalfLength, double ZHalfLength) - : m_xHalfLength (XHalfLength) - , m_yHalfLength (YHalfLength) - , m_zHalfLength (ZHalfLength) -{ -} +GeoBox::GeoBox (double XHalfLength, double YHalfLength, double ZHalfLength): + m_xHalfLength {XHalfLength}, + m_yHalfLength {YHalfLength}, + m_zHalfLength {ZHalfLength} {} -GeoBox::~GeoBox() -{ -} -double GeoBox::volume () const -{ +double GeoBox::volume () const { return 8.0 * m_xHalfLength * m_yHalfLength * m_zHalfLength; } -const std::string & GeoBox::type () const -{ - return s_classType; +void GeoBox::extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const { + xmin = -m_xHalfLength; + ymin = -m_yHalfLength; + zmin = -m_zHalfLength; + xmax = m_xHalfLength; + ymax = m_yHalfLength; + zmax = m_zHalfLength; } -ShapeType GeoBox::typeID () const -{ - return s_classTypeID; +bool GeoBox::contains (double x, double y, double z) const { + double distx = std::abs(x) - m_xHalfLength; + double disty = std::abs(y) - m_yHalfLength; + double distz = std::abs(z) - m_zHalfLength; + return (std::max(std::max(distx, disty), distz) <= 0.0); } -void GeoBox::exec (GeoShapeAction *action) const -{ + +void GeoBox::exec (GeoShapeAction *action) const { action->handleBox(this); } diff --git a/GeoModelCore/GeoModelKernel/src/GeoCons.cxx b/GeoModelCore/GeoModelKernel/src/GeoCons.cxx index 1082bfb271db4c122e57bf9ccd78e320976d51d4..2fcad24bf54f8c73bb8db7c7b7946ee0f9a0d721 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoCons.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoCons.cxx @@ -1,9 +1,10 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #include "GeoModelKernel/GeoCons.h" #include "GeoModelKernel/GeoShapeAction.h" +#include <cmath> const std::string GeoCons::s_classType = "Cons"; const ShapeType GeoCons::s_classTypeID = 0x11; @@ -19,28 +20,47 @@ GeoCons::GeoCons (double RMin1, double RMin2, double RMax1, double RMax2, double { } -GeoCons::~GeoCons() -{ -} double GeoCons::volume () const { - return (m_dPhi * (1./3)) * m_dZ * (m_rMax1 * m_rMax1 + m_rMax2 * m_rMax2 + m_rMax1 * m_rMax2 - - m_rMin1 * m_rMin1 - m_rMin2 * m_rMin2 - - m_rMin1 * m_rMin2); + return (m_dPhi * (1./3.)) * m_dZ * + (m_rMax1 * m_rMax1 + m_rMax2 * m_rMax2 + m_rMax1 * m_rMax2 - + m_rMin1 * m_rMin1 - m_rMin2 * m_rMin2 - m_rMin1 * m_rMin2); } -const std::string & GeoCons::type () const +void GeoCons::extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const { - return s_classType; + double rmin = std::min(m_rMin1, m_rMin2); + double rmax = std::max(m_rMax1, m_rMax2); + GeoShape::diskExtent(rmin, rmax, m_sPhi, m_dPhi, xmin, ymin, xmax, ymax); + zmin =-m_dZ; + zmax = m_dZ; } -ShapeType GeoCons::typeID () const +bool GeoCons::contains (double x, double y, double z) const { - return s_classTypeID; +#ifndef M_PI + constexpr double M_PI = 3.14159265358979323846; +#endif + if (std::abs(z) - m_dZ > 0.0) return false; + double t = 0.5 * (1.0 + z / m_dZ); + double rmin = m_rMin1 + (m_rMin2 - m_rMin1) * t; + double rmax = m_rMax1 + (m_rMax2 - m_rMax1) * t; + double rr = x * x + y * y; + if (rr > rmax * rmax || rr < rmin * rmin) return false; + if (m_dPhi >= 2.0 * M_PI) return true; + + GeoTrf::Vector2D r(x, y); + GeoTrf::Vector2D ns(std::sin(m_sPhi), -std::cos(m_sPhi)); + GeoTrf::Vector2D ne(-std::sin(m_sPhi + m_dPhi), std::cos(m_sPhi + m_dPhi)); + double ds = ns.dot(r); + double de = ne.dot(r); + return (m_dPhi <= M_PI) ? (ds <= 0 && de <= 0) : (ds <= 0 || de <= 0); } -void GeoCons::exec (GeoShapeAction *action) const -{ + + +void GeoCons::exec (GeoShapeAction *action) const { action->handleCons(this); } diff --git a/GeoModelCore/GeoModelKernel/src/GeoDefinitions.cxx b/GeoModelCore/GeoModelKernel/src/GeoDefinitions.cxx index c67561a1474d634bf843e27faaa5cf36ac2c2286..4c55243d0983845040ba65e8b3be91193b1d2905 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoDefinitions.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoDefinitions.cxx @@ -1,28 +1,109 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration */ #include "GeoModelKernel/GeoDefinitions.h" +#include "GeoModelKernel/Units.h" +#include <cmath> -namespace GeoTrf -{ - GeoRotation::GeoRotation(double phi, double theta, double psi) - { - double sinPhi = std::sin( phi ), cosPhi = std::cos( phi ); - double sinTheta = std::sin( theta ), cosTheta = std::cos( theta ); - double sinPsi = std::sin( psi ), cosPsi = std::cos( psi ); - - this->operator()(0,0) = cosPsi * cosPhi - cosTheta * sinPhi * sinPsi; - this->operator()(0,1) = cosPsi * sinPhi + cosTheta * cosPhi * sinPsi; - this->operator()(0,2) = sinPsi * sinTheta; - - this->operator()(1,0) = - sinPsi * cosPhi - cosTheta * sinPhi * cosPsi; - this->operator()(1,1) = - sinPsi * sinPhi + cosTheta * cosPhi * cosPsi; - this->operator()(1,2) = cosPsi * sinTheta; - - this->operator()(2,0) = sinTheta * sinPhi; - this->operator()(2,1) = - sinTheta * cosPhi; - this->operator()(2,2) = cosTheta; +namespace { + constexpr double rotTolerance = 0.01 * GeoModelKernelUnits::deg; + + inline double cutOff(const double val, const double cutOff) { + return std::abs(val) > cutOff ? val : 0.; + } + inline double calcAngle(const double y, const double x) { + return cutOff(std::atan2(cutOff(y, std::numeric_limits<float>::epsilon()), + cutOff(x, std::numeric_limits<float>::epsilon())), rotTolerance); } } +namespace GeoTrf { + + + GeoRotation::GeoRotation(double phi, double theta, double psi): + GeoRotation{EulerAngles{phi, theta, psi}} {} + + GeoRotation::GeoRotation(const EulerAngles& angles): + RotationMatrix3D{get3DRotMatZ(angles.phi) * + get3DRotMatX(angles.theta) * + get3DRotMatZ(angles.psi)} {} + + + GeoRotation::GeoRotation(const CoordEulerAngles& angles): + RotationMatrix3D{get3DRotMatZ(angles.gamma) * + get3DRotMatY(angles.beta)* + get3DRotMatX(angles.alpha)} {} + + + + CoordEulerAngles getCoordRotationAngles(const Transform3D& trans) { + return getCoordRotationAngles(trans.linear()); + } + CoordEulerAngles getCoordRotationAngles(const RotationMatrix3D& rot) { + CoordEulerAngles toRet{}; + const double beta1 = -std::asin(std::clamp(rot(2,0), -1., 1.)); + const double beta2 = M_PI - beta1; + /// Choose the beta value where cos(\beta) > 0 + toRet.beta = cutOff(std::cos(beta1) >= 0. ? beta1 : beta2, rotTolerance); + /// Check that cos(beta) != 0. + const double cosBeta = std::cos(toRet.beta); + if (std::abs(cosBeta) > std::numeric_limits<float>::epsilon()) { + const double iCosBeta = 1./ cosBeta; + toRet.gamma = calcAngle(rot(1,0) * iCosBeta, rot(0,0) * iCosBeta); + toRet.alpha = calcAngle(rot(2,1) * iCosBeta, rot(2,2) * iCosBeta); + } else { + toRet.beta = rot(2,0) > 0 ? -M_PI_2 : M_PI_2; + toRet.alpha = rot(2,0) < 0 ? calcAngle(rot(0,1), rot(0,2)) : + calcAngle(-rot(0,1), -rot(0,2)); + } + return toRet; + } + EulerAngles getGeoRotationAngles(const Transform3D& trans) { + return getGeoRotationAngles(trans.linear()); + } + EulerAngles getGeoRotationAngles(const RotationMatrix3D& rotMat){ + EulerAngles toRet{}; + toRet.theta = cutOff(std::acos(std::clamp(rotMat(2,2),-1., 1.)), rotTolerance); + const double sinTheta = std::sin(toRet.theta); + if (std::abs(sinTheta) > std::numeric_limits<float>::epsilon()) { + toRet.phi = calcAngle(sinTheta* rotMat(0,2), -sinTheta * rotMat(1,2)); + toRet.psi = calcAngle(sinTheta *rotMat(2,0), sinTheta * rotMat(2,1)); + } else { + toRet.theta = rotMat(2,2) > 0 ? 0. : M_PI; + toRet.phi = calcAngle(rotMat(1,0), rotMat(0,0)); + } + + return toRet; + } + + + + int EulerAngles::compare(const EulerAngles& other) const { + if (std::abs(phi - other.phi) > rotTolerance) return phi < other.phi ? -1 : 1; + if (std::abs(theta - other.theta) > rotTolerance) return theta < other.theta ? -1 : 1; + if (std::abs(psi - other.psi) > rotTolerance) return psi < other.psi ? -1 : 1; + return 0; + } + bool EulerAngles::operator<(const EulerAngles& other) const { + return compare(other) < 0; + } + EulerAngles::operator bool() const { + return std::abs(phi) > rotTolerance || std::abs(theta) > rotTolerance || std::abs(psi) > rotTolerance; + } + + int CoordEulerAngles::compare(const CoordEulerAngles& other) const { + if (std::abs(alpha - other.alpha) > rotTolerance) return alpha < other.alpha ? -1 : 1; + if (std::abs(beta - other.beta) > rotTolerance) return beta < other.beta ? -1 : 1; + if (std::abs(gamma - other.gamma) > rotTolerance) return gamma < other.gamma ? -1 : 1; + return 0; + } + bool CoordEulerAngles::operator<(const CoordEulerAngles& other) const { + return compare(other) < 0; + } + CoordEulerAngles::operator bool() const { + return std::abs(alpha) > rotTolerance || std::abs(beta) > rotTolerance || std::abs(gamma) > rotTolerance; + } + +} + diff --git a/GeoModelCore/GeoModelKernel/src/GeoEllipticalTube.cxx b/GeoModelCore/GeoModelKernel/src/GeoEllipticalTube.cxx index d0848e1111b67561cdefd7ad37205c3c2429c5fe..e356b15e1ac2b6c5805fe1b2f28001d0d2c741dd 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoEllipticalTube.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoEllipticalTube.cxx @@ -2,47 +2,47 @@ Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration */ -#include <cmath> #include "GeoModelKernel/GeoPolyhedrizeAction.h" #include "GeoModelKernel/GeoShapeAction.h" +#include <cmath> #include "GeoModelKernel/GeoEllipticalTube.h" const std::string GeoEllipticalTube::s_classType = "EllipticalTube"; const ShapeType GeoEllipticalTube::s_classTypeID = 0x22; - -GeoEllipticalTube::GeoEllipticalTube(double XHalfLength, double YHalfLength, double ZHalfLength) - : m_xHalfLength(XHalfLength) - , m_yHalfLength(YHalfLength) - , m_zHalfLength(ZHalfLength) -{ -} +GeoEllipticalTube::GeoEllipticalTube(double XHalfLength, double YHalfLength, double ZHalfLength): + m_xHalfLength{XHalfLength}, + m_yHalfLength{YHalfLength}, + m_zHalfLength{ZHalfLength} {} -GeoEllipticalTube::~GeoEllipticalTube() -{ -} - double GeoEllipticalTube::volume () const { #ifndef M_PI - double M_PI = acos (-1.0); + constexpr double M_PI = 3.14159265358979323846; #endif - return 2 * M_PI * m_xHalfLength * m_yHalfLength * m_zHalfLength; + return 2.0 * M_PI * m_xHalfLength * m_yHalfLength * m_zHalfLength; } -const std::string & GeoEllipticalTube::type () const +void GeoEllipticalTube::extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const { - return s_classType; + xmin =-m_xHalfLength; + ymin =-m_yHalfLength; + zmin =-m_zHalfLength; + xmax = m_xHalfLength; + ymax = m_yHalfLength; + zmax = m_zHalfLength; } -ShapeType GeoEllipticalTube::typeID () const +bool GeoEllipticalTube::contains (double x, double y, double z) const { - return s_classTypeID; + if (std::abs(z) - m_zHalfLength > 0.0) return false; + return ((x * x) / (m_xHalfLength * m_xHalfLength) + + (y * y) / (m_yHalfLength * m_yHalfLength) <= 1.0); } -void GeoEllipticalTube::exec (GeoShapeAction *action) const -{ + +void GeoEllipticalTube::exec (GeoShapeAction *action) const { action->handleEllipticalTube(this); } - diff --git a/GeoModelCore/GeoModelKernel/src/GeoFacet.cxx b/GeoModelCore/GeoModelKernel/src/GeoFacet.cxx index 697edf3c99253cc4196caf39c5f748d0a86cad3a..b231bec81a1130d6c41ce5313fa22af70c66c239 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoFacet.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoFacet.cxx @@ -20,9 +20,6 @@ GeoTriangularFacet::GeoTriangularFacet(GeoFacetVertex v0 } -GeoTriangularFacet::~GeoTriangularFacet() -{ -} // ___________________ Triangular Facet ________________________ GeoQuadrangularFacet::GeoQuadrangularFacet(GeoFacetVertex v0 @@ -41,7 +38,3 @@ GeoQuadrangularFacet::GeoQuadrangularFacet(GeoFacetVertex v0 m_vertices[3] = v3; } - -GeoQuadrangularFacet::~GeoQuadrangularFacet() -{ -} diff --git a/GeoModelCore/GeoModelKernel/src/GeoFullPhysVol.cxx b/GeoModelCore/GeoModelKernel/src/GeoFullPhysVol.cxx index 0521c9659945cdbcdbd6ac1325c6f6dfdffeebf2..9022dbd2e13f9687cae239f62fe489c96b98a587 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoFullPhysVol.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoFullPhysVol.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #include "GeoModelKernel/GeoFullPhysVol.h" @@ -12,23 +12,14 @@ #include <algorithm> GeoFullPhysVol::GeoFullPhysVol (const GeoLogVol* LogVol) - : GeoVFullPhysVol(LogVol) - , m_cloneOrigin(nullptr) -{ -} - -GeoFullPhysVol::~GeoFullPhysVol() -{ - for(const GeoGraphNode* daughter : m_daughters) daughter->unref(); - if(m_cloneOrigin && m_cloneOrigin!=this) m_cloneOrigin->unref(); -} + : GeoVFullPhysVol(LogVol){ } void GeoFullPhysVol::add(GeoGraphNode* graphNode) { if(m_cloneOrigin) throw std::runtime_error("Attempt to modify contents of a cloned FPV"); std::scoped_lock<std::mutex> guard(m_mutex); - m_daughters.push_back(graphNode); - graphNode->ref(); + GeoIntrusivePtr<GeoGraphNode> nodePtr{graphNode}; + m_daughters.emplace_back(nodePtr); graphNode->dockTo(this); } @@ -123,27 +114,18 @@ unsigned int GeoFullPhysVol::getNChildVolAndST() const return cv.getCount(); } -/// Meaning of the input parameter 'attached' -/// TRUE: all cloned volumes are meant to stay identical to their clone origin for the lifetime -/// further changes are permitted neither in the origin nor in the clone results -/// -/// FALSE: use this value if you expect further changes in either clone origing or its clone results -/// which don't need to be syncronized. The clone origin and its clone are identical ONLY by -/// the time of cloning, further identity is not guaranteed GeoFullPhysVol* GeoFullPhysVol::clone(bool attached) { GeoFullPhysVol* clone = new GeoFullPhysVol(this->getLogVol()); - for(unsigned int ind = 0; ind < this->m_daughters.size(); ind++) { - GeoGraphNode* daughter =(GeoGraphNode*) m_daughters[ind]; + for(auto daughter : m_daughters) { clone->add(daughter); } if(attached) { - if(this->m_cloneOrigin==0) { - this->m_cloneOrigin = this; + if(!m_cloneOrigin) { + m_cloneOrigin = this; } - clone->m_cloneOrigin = this->m_cloneOrigin; - this->m_cloneOrigin->ref(); + clone->m_cloneOrigin = m_cloneOrigin; } return clone; @@ -159,8 +141,6 @@ const GeoFullPhysVol* GeoFullPhysVol::cloneOrigin() const /// Don't call it until geometry has been completely translated to G4 void GeoFullPhysVol::clear() { - for(size_t i=0; i<m_daughters.size(); i++) - m_daughters[i]->unref(); m_daughters.clear(); } @@ -239,19 +219,17 @@ unsigned int GeoFullPhysVol::getNChildNodes() const return m_daughters.size(); } -const GeoGraphNode * const * GeoFullPhysVol::getChildNode(unsigned int i) const -{ +const GeoGraphNode * const * GeoFullPhysVol::getChildNode(unsigned int i) const { std::scoped_lock<std::mutex> guard(m_mutex); - return &(m_daughters[i]); + return m_daughters[i]; } const GeoGraphNode * const * GeoFullPhysVol::findChildNode(const GeoGraphNode * n) const { std::scoped_lock<std::mutex> guard(m_mutex); - std::vector<const GeoGraphNode *>::const_iterator i = std::find(m_daughters.begin(),m_daughters.end(),n); + std::vector<GeoIntrusivePtr<GeoGraphNode>>::const_iterator i = std::find(m_daughters.begin(),m_daughters.end(),n); if (i==m_daughters.end()) { return nullptr; } - else { - return &*i; - } + return (*i); + } diff --git a/GeoModelCore/GeoModelKernel/src/GeoGenericTrap.cxx b/GeoModelCore/GeoModelKernel/src/GeoGenericTrap.cxx index 260cf3513eb5b1ff0b4f59f9d09666151b21af3e..31e1b31b884b2812229c554639c88a4cc4b24fcb 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoGenericTrap.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoGenericTrap.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #include "GeoModelKernel/GeoGenericTrap.h" @@ -10,42 +10,67 @@ const ShapeType GeoGenericTrap::s_classTypeID = 0x23; GeoGenericTrap::GeoGenericTrap(double ZHalfLength, const GeoGenericTrapVertices& Vertices) : m_zHalfLength(ZHalfLength) - , m_vertices(Vertices) -{ -} + , m_vertices(Vertices) {} -GeoGenericTrap::~GeoGenericTrap() -{ -} double GeoGenericTrap::volume() const { - // -- ToDo - return 0.; -} + // diagonals + GeoTwoVector a = m_vertices[3] - m_vertices[1]; + GeoTwoVector b = m_vertices[2] - m_vertices[0]; + GeoTwoVector c = m_vertices[7] - m_vertices[5]; + GeoTwoVector d = m_vertices[6] - m_vertices[4]; -const std::string& GeoGenericTrap::type() const -{ - return s_classType; -} + // kross products + double ab = a.x()*b.y() - a.y()*b.x(); + double cd = c.x()*d.y() - c.y()*d.x(); + double ad = a.x()*d.y() - a.y()*d.x(); + double cb = c.x()*b.y() - c.y()*b.x(); -ShapeType GeoGenericTrap::typeID() const -{ - return s_classTypeID; + return m_zHalfLength * ((ab + cd)* (1./3.) + (ad + cb)* (1./6.)); } -void GeoGenericTrap::exec(GeoShapeAction *action) const +void GeoGenericTrap::extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const { - action->handleGenericTrap(this); + xmin = xmax = m_vertices[0].x(); + ymin = ymax = m_vertices[0].y(); + int nv = m_vertices.size(); + for (int i = 1; i < nv; ++i) + { + if (xmin > m_vertices[i].x()) xmin = m_vertices[i].x(); + if (xmax < m_vertices[i].x()) xmax = m_vertices[i].x(); + if (ymin > m_vertices[i].y()) ymin = m_vertices[i].y(); + if (ymax < m_vertices[i].y()) ymax = m_vertices[i].y(); + } + zmin =-m_zHalfLength; + zmax = m_zHalfLength; } -double GeoGenericTrap::getZHalfLength() const +bool GeoGenericTrap::contains (double x, double y, double z) const { - return m_zHalfLength; + if (std::abs(z) - m_zHalfLength > 0.0) return false; + double t = 0.5 * (1.0 + z / m_zHalfLength); + GeoTrf::Vector2D v[4]; + v[0] = m_vertices[0] + (m_vertices[4] - m_vertices[0]) * t; + v[1] = m_vertices[1] + (m_vertices[5] - m_vertices[1]) * t; + v[2] = m_vertices[2] + (m_vertices[6] - m_vertices[2]) * t; + v[3] = m_vertices[3] + (m_vertices[7] - m_vertices[3]) * t; + int nv = 4; + bool in = false; + for (int i = 0, k = nv - 1; i < nv; k = i++) + { + if ((v[i].y() > y) != (v[k].y() > y)) + { + double ctg = (v[k].x() - v[i].x()) / (v[k].y() - v[i].y()); + in ^= (x < (y - v[i].y()) * ctg + v[i].x()); + } + } + return in; } -const GeoGenericTrapVertices& GeoGenericTrap::getVertices() const +void GeoGenericTrap::exec(GeoShapeAction *action) const { - return m_vertices; + action->handleGenericTrap(this); } diff --git a/GeoModelCore/GeoModelKernel/src/GeoGraphNode.cxx b/GeoModelCore/GeoModelKernel/src/GeoGraphNode.cxx index 49ab96dec4b489d53e169b619534ee66e98eb741..d39f2cd75ba856c116642e35b83f6ffe318b1c4c 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoGraphNode.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoGraphNode.cxx @@ -1,17 +1,10 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #include "GeoModelKernel/GeoGraphNode.h" #include "GeoModelKernel/GeoNodeAction.h" -GeoGraphNode::GeoGraphNode () -{ -} - -GeoGraphNode::~GeoGraphNode() -{ -} void GeoGraphNode::exec (GeoNodeAction *action) const { diff --git a/GeoModelCore/GeoModelKernel/src/GeoLogVol.cxx b/GeoModelCore/GeoModelKernel/src/GeoLogVol.cxx index 4827936b28de423678f7cfb5ea6815fc52b61fab..3f86839f0cb12d028b2ad3cd8f138daaf1c7c201 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoLogVol.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoLogVol.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #include "GeoModelKernel/GeoLogVol.h" @@ -7,15 +7,5 @@ GeoLogVol::GeoLogVol (const std::string &Name, const GeoShape *Shape, const GeoMaterial *Material) : m_name (Name) , m_material (Material) - , m_shape (Shape) -{ - m_material->ref (); - m_shape->ref (); -} - -GeoLogVol::~GeoLogVol() -{ - m_material->unref (); - m_shape->unref (); -} + , m_shape (Shape){} diff --git a/GeoModelCore/GeoModelKernel/src/GeoMaterial.cxx b/GeoModelCore/GeoModelKernel/src/GeoMaterial.cxx index 26f3e09e7bd68d418f91269db58660da4ec3269d..1b693c83509ae75b1d4b5386323765fb3ee8fc12 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoMaterial.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoMaterial.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #include "GeoModelKernel/GeoMaterial.h" @@ -213,61 +213,37 @@ const double unsigned int GeoMaterial::s_lastID = 0; -GeoMaterial::GeoMaterial (const std::string &Name, double Density) - : m_name(Name) - , m_density(Density) +GeoMaterial::GeoMaterial (const std::string& name, double density) + : m_name(name) + , m_density(density) , m_iD(s_lastID++) - , m_radLength(0) - , m_intLength(0) - , m_dedDxConst(0) - , m_deDxI0(0) - , m_locked(false) { } -GeoMaterial::~GeoMaterial() -{ - for (size_t i = 0; i < m_element.size (); i++) - { - m_element[i]->unref (); - } -} - void GeoMaterial::add (const GeoElement* element, double fraction) { // You can only add materials until you call "lock"... - if (!m_locked) - { - std::vector <const GeoElement *>::iterator e = std::find(m_element.begin(),m_element.end(),element); - if (e==m_element.end()) { - m_element.push_back (element); - m_fraction.push_back (fraction); - element->ref (); - } - else { - int n = e-m_element.begin(); - m_fraction[n]+=fraction; - } - } - else - { - throw std::out_of_range ("Element added after material locked"); - } + if(m_locked) throw std::out_of_range ("Element added after material locked"); + + auto e = std::find(m_elements.begin(),m_elements.end(),element); + if (e==m_elements.end()) { + m_elements.push_back (element); + m_fractions.push_back (fraction); + element->ref (); + } + else { + int n = e-m_elements.begin(); + m_fractions[n]+=fraction; + } } void GeoMaterial::add (const GeoMaterial* material, double fraction) { - if (!m_locked) - { - for (size_t e = 0; e < material->getNumElements (); e++) - { - add(material->m_element[e],fraction * material->m_fraction[e]); - } - } - else - { - throw std::out_of_range ("Material added after material locked"); - } + if(m_locked) throw std::out_of_range ("Material added after material locked"); + + for(size_t e = 0; e < material->getNumElements (); ++e) { + add(material->m_elements[e],fraction * material->m_fractions[e]); + } } void GeoMaterial::lock () @@ -292,12 +268,7 @@ void GeoMaterial::lock () // // //--------------------------------------------// - if (getNumElements () == 0) - { - throw std::out_of_range ("Attempt to lock a material with no elements "+getName()); - return; - } - + if(getNumElements() == 0) throw std::out_of_range ("Attempt to lock a material with no elements "+getName()); //--------------------------------------------// // // @@ -305,42 +276,44 @@ void GeoMaterial::lock () double dEDxConstant = 0, dEDxI0 = 0, NILinv = 0.0, radInv = 0.0; - { // ===============Renormalization================================ - double wSum=std::accumulate(m_fraction.begin(),m_fraction.end(),0.0); - if (fabs(wSum-1.0)>FLT_EPSILON) // 'FLT_EPSILON' defined in <cfloat> - { - if(std::getenv("GEOMODELKERNEL_VERBOSE")) { - std::cerr << "Warning in material " - << m_name - << ". Mass fractions sum to " - << wSum << "; renormalizing to 1.0" << std::endl; - } + // ===============Renormalization================================ + { + double wSum=std::accumulate(m_fractions.begin(),m_fractions.end(),0.0); + if(fabs(wSum-1.0)>FLT_EPSILON) { // 'FLT_EPSILON' defined in <cfloat> + if(std::getenv("GEOMODELKERNEL_VERBOSE")) { + std::cerr << "Warning in material " + << m_name + << ". Mass fractions sum to " + << wSum << "; renormalizing to 1.0" << std::endl; + } } double inv_wSum = 1. / wSum; - for (size_t e=0;e<getNumElements();e++) {m_fraction[e]*=inv_wSum;} - } // ============================================================== + for(size_t e=0;e<getNumElements();++e) { + m_fractions[e]*=inv_wSum; + } + } + // ============================================================== const double inv_lambda0 = 1. / lambda0; - for (size_t e = 0; e < getNumElements (); e++) - { - double w = getFraction (e); // Weight fraction. - double Z = m_element[e]->getZ (); // Atomic number - double A = m_element[e]->getA (); // Atomic mass. - double N = m_element[e]->getN (); // Number of nucleons. - double dovera = m_density ? m_density / A : 0; // don't crash if both are 0 - double n = m_fraction[e] * GeoModelKernelUnits::Avogadro * dovera; // Number density. - int iZ = (int) (m_element[e]->getZ () + 0.5) - 1; // Atomic number index - - dEDxConstant += w * C0 * dovera * Z; - // Make sure we don't overflow the table: - // the `Ether' special `element' has Z set to 500. - if (iZ >= 0 && iZ < (std::end(s_ionizationPotential)-std::begin(s_ionizationPotential))) - dEDxI0 += w * s_ionizationPotential[iZ]; - NILinv += n * pow (N, 2.0 / 3.0) * GeoModelKernelUnits::amu * inv_lambda0; - - double nAtomsPerVolume = A ? GeoModelKernelUnits::Avogadro*m_density*m_fraction[e]/A : 0.; - radInv += (nAtomsPerVolume*m_element[e]->getRadTsai()); - } + for(size_t e = 0; e < getNumElements (); ++e) { + double w = getFraction (e); // Weight fraction. + double Z = m_elements[e]->getZ (); // Atomic number + double A = m_elements[e]->getA (); // Atomic mass. + double N = m_elements[e]->getN (); // Number of nucleons. + double dovera = m_density ? m_density / A : 0; // don't crash if both are 0 + double n = m_fractions[e] * GeoModelKernelUnits::Avogadro * dovera; // Number density. + int iZ = (int) (m_elements[e]->getZ () + 0.5) - 1; // Atomic number index + + dEDxConstant += w * C0 * dovera * Z; + // Make sure we don't overflow the table: + // the `Ether' special `element' has Z set to 500. + if (iZ >= 0 && iZ < (std::end(s_ionizationPotential)-std::begin(s_ionizationPotential))) + dEDxI0 += w * s_ionizationPotential[iZ]; + NILinv += n * pow (N, 2.0 / 3.0) * GeoModelKernelUnits::amu * inv_lambda0; + + double nAtomsPerVolume = A ? GeoModelKernelUnits::Avogadro*m_density*m_fractions[e]/A : 0.; + radInv += (nAtomsPerVolume*m_elements[e]->getRadTsai()); + } m_dedDxConst = dEDxConstant; m_deDxI0 = dEDxI0 ; m_intLength = NILinv ? 1.0 / NILinv : 0; @@ -382,7 +355,6 @@ double GeoMaterial::getDeDxMin () const // -----------------------------------------------------------// return m_dedDxConst * ConstToMin; - } double GeoMaterial::getRadLength () const @@ -403,19 +375,19 @@ unsigned int GeoMaterial::getNumElements () const { if (!m_locked) throw std::out_of_range ("Material accessed before lock"); - return m_element.size (); + return m_elements.size(); } const GeoElement* GeoMaterial::getElement (unsigned int i) const { if (!m_locked) throw std::out_of_range ("Material accessed before lock"); - return m_element[i]; + return m_elements[i]; } double GeoMaterial::getFraction (int i) const { if (!m_locked) throw std::out_of_range ("Material accessed before lock"); - return m_fraction[i]; + return m_fractions[i]; } diff --git a/GeoModelCore/GeoModelKernel/src/GeoPVConstLink.cxx b/GeoModelCore/GeoModelKernel/src/GeoPVConstLink.cxx deleted file mode 100755 index e65e17fa92431293c34cdd05501928f758b63358..0000000000000000000000000000000000000000 --- a/GeoModelCore/GeoModelKernel/src/GeoPVConstLink.cxx +++ /dev/null @@ -1,79 +0,0 @@ -/* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -*/ - -#include "GeoModelKernel/GeoPVConstLink.h" - -GeoPVConstLink::GeoPVConstLink() - : m_ptr (0) -{ -} - -GeoPVConstLink::GeoPVConstLink(const GeoPVConstLink &right) - : m_ptr (right.m_ptr) -{ -} - -GeoPVConstLink::GeoPVConstLink (const GeoVPhysVol *addr) - : m_ptr (const_cast < GeoVPhysVol * >(addr)) -{ -} - -GeoPVConstLink::~GeoPVConstLink() -{ -} - - -int GeoPVConstLink::operator==(const GeoPVConstLink &right) const -{ - return m_ptr == right.m_ptr; -} - -int GeoPVConstLink::operator!=(const GeoPVConstLink &right) const -{ - return m_ptr != right.m_ptr; -} - -int GeoPVConstLink::operator<(const GeoPVConstLink &right) const -{ - return m_ptr < right.m_ptr; -} - -int GeoPVConstLink::operator>(const GeoPVConstLink &right) const -{ - return m_ptr > right.m_ptr; -} - -int GeoPVConstLink::operator<=(const GeoPVConstLink &right) const -{ - return m_ptr <= right.m_ptr; -} - -int GeoPVConstLink::operator>=(const GeoPVConstLink &right) const -{ - return m_ptr >= right.m_ptr; -} - -const GeoVPhysVol & GeoPVConstLink::operator * () const -{ - return *m_ptr; -} - -const GeoVPhysVol * GeoPVConstLink::operator -> () const -{ - return m_ptr; -} - -GeoPVConstLink::operator bool () const -{ - return m_ptr; -} - -GeoPVConstLink& GeoPVConstLink::operator = (const GeoPVConstLink& right) -{ - if (this != &right) - { - m_ptr = right.m_ptr; - } - return *this; -} diff --git a/GeoModelCore/GeoModelKernel/src/GeoPVLink.cxx b/GeoModelCore/GeoModelKernel/src/GeoPVLink.cxx deleted file mode 100755 index 7bb581cddf7e716fffdf3f2a87f1bf535025f24d..0000000000000000000000000000000000000000 --- a/GeoModelCore/GeoModelKernel/src/GeoPVLink.cxx +++ /dev/null @@ -1,54 +0,0 @@ -/* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -*/ - -#include "GeoModelKernel/GeoPVLink.h" - -GeoPVLink::GeoPVLink() - : GeoPVConstLink (0) -{ -} - -GeoPVLink::GeoPVLink(const GeoPVLink &right) - : GeoPVConstLink (right) -{ -} - -GeoPVLink::GeoPVLink (const GeoVPhysVol *addr) - : GeoPVConstLink (addr) -{ -} - -GeoPVLink::~GeoPVLink() -{ -} - -GeoVPhysVol & GeoPVLink::operator * () -{ - return *m_ptr; -} - -GeoVPhysVol * GeoPVLink::operator -> () -{ - return m_ptr; -} - -const GeoVPhysVol & GeoPVLink::operator * () const -{ - return *m_ptr; -} - -const GeoVPhysVol * GeoPVLink::operator -> () const -{ - return m_ptr; -} - -GeoPVLink& GeoPVLink::operator = (const GeoPVLink& right) -{ - if (&right != this) - { - m_ptr = right.m_ptr; - } - return *this; -} - diff --git a/GeoModelCore/GeoModelKernel/src/GeoPara.cxx b/GeoModelCore/GeoModelKernel/src/GeoPara.cxx index 00c49a027b8539669efe1ba356908cd26bc37679..c1634dee1b6ee639b4d7da5e948d152f0d8148eb 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoPara.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoPara.cxx @@ -19,33 +19,50 @@ m_alpha (Alpha), m_phi (Phi) {} -GeoPara::~GeoPara() -{} - double GeoPara::volume () const + +double GeoPara::volume () const { - //## begin GeoPara::volume%3CD2A6DB00FC.body preserve=yes - GeoTrf::Vector3D - v0 (1, 0, 0), - v1 (sin (m_alpha), cos (m_alpha), 0), - v2 (sin (m_theta) * cos (m_phi), sin (m_theta) * sin (m_phi), cos (m_theta)); - double factor = (v0.cross (v1).dot (v2)); - - return 8.0 * factor * m_xHalfLength * m_yHalfLength * m_zHalfLength; + return 8.0 * m_xHalfLength * m_yHalfLength * m_zHalfLength; } -const std::string & GeoPara::type () const +void GeoPara::extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const { - return s_classType; + double dx = m_xHalfLength; + double dy = m_yHalfLength; + double dz = m_zHalfLength; + + double x0 = dz * std::tan(m_theta) * std::cos(m_phi); + double x1 = dy * std::tan(m_alpha); + xmin = std::min(std::min(std::min(-x0-x1-dx, -x0+x1-dx), x0-x1-dx), x0+x1-dx); + xmax = std::max(std::max(std::max(-x0-x1+dx, -x0+x1+dx), x0-x1+dx), x0+x1+dx); + + double y0 = dz * std::tan(m_theta) * std::sin(m_phi); + ymin = std::min(-y0-dy, y0-dy); + ymax = std::max(-y0+dy, y0+dy); + + zmin = -dz; + zmax = dz; } -ShapeType GeoPara::typeID () const +bool GeoPara::contains (double x, double y, double z) const { - return s_classTypeID; + double cosPhi = std::cos(m_phi); + double sinPhi = std::sin(m_phi); + double tanTheta = std::tan(m_theta); + double tanAlpha = std::tan(m_alpha); + + double z0 = z; + double y0 = y - z0 * tanTheta * sinPhi; + double x0 = x - y0 * tanAlpha - z0 * tanTheta * cosPhi; + double distx = std::abs(x0) - m_xHalfLength; + double disty = std::abs(y0) - m_yHalfLength; + double distz = std::abs(z0) - m_zHalfLength; + return (std::max(std::max(distx, disty), distz) <= 0.0); } void GeoPara::exec (GeoShapeAction *action) const { - action->handlePara(this); + action->handlePara(this); } - diff --git a/GeoModelCore/GeoModelKernel/src/GeoPcon.cxx b/GeoModelCore/GeoModelKernel/src/GeoPcon.cxx index a7407b86c71b0855b93d08a1e94c330a6a52bca0..858cfdf128c828f26222d926e5e505781de77143 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoPcon.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoPcon.cxx @@ -16,38 +16,80 @@ GeoPcon::GeoPcon (double SPhi, double DPhi) { } -GeoPcon::~GeoPcon() -{ -} double GeoPcon::volume () const { if (!isValid ()) throw std::runtime_error ("Volume requested for incomplete polycone"); - double v = 0; - for (size_t s = 0; s < getNPlanes () - 1; s++) - { - double fDz = fabs (getZPlane (s + 1) - getZPlane (s)) / 2.0; - double fRmin1 = getRMinPlane (s + 1); - double fRmin2 = getRMinPlane (s); - double fRmax1 = getRMaxPlane (s + 1); - double fRmax2 = getRMaxPlane (s); - v += - (m_dPhi * (1./3)) * fDz * (fRmax1 * fRmax1 + fRmax2 * fRmax2 + - fRmax1 * fRmax2 - fRmin1 * fRmin1 - - fRmin2 * fRmin2 - fRmin1 * fRmin2); - } - return v; + double vol = 0; + for (size_t k = 0; k < getNPlanes() - 1; ++k) + { + double fDz = std::abs(getZPlane(k + 1) - getZPlane(k)) / 2.0; + double fRmin1 = getRMinPlane(k + 1); + double fRmin2 = getRMinPlane(k); + double fRmax1 = getRMaxPlane(k + 1); + double fRmax2 = getRMaxPlane(k); + vol += (m_dPhi * (1./3)) * fDz * + (fRmax1 * fRmax1 + fRmax2 * fRmax2 + fRmax1 * fRmax2 - + fRmin1 * fRmin1 - fRmin2 * fRmin2 - fRmin1 * fRmin2); + } + return vol; } -const std::string & GeoPcon::type () const +void GeoPcon::extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const { - return s_classType; + if (!isValid ()) + throw std::runtime_error ("Extent requested for incomplete polycone"); + double rmin = getRMinPlane(0); + double rmax = getRMaxPlane(0); + zmin = zmax = getZPlane(0); + for (size_t i = 1; i < getNPlanes(); ++i) + { + rmin = std::min(rmin, getRMinPlane(i)); + rmax = std::max(rmax, getRMaxPlane(i)); + zmin = std::min(zmin, getZPlane(i)); + zmax = std::max(zmax, getZPlane(i)); + } + GeoShape::diskExtent(rmin, rmax, getSPhi(), getDPhi(), xmin, ymin, xmax, ymax); } -ShapeType GeoPcon::typeID () const +bool GeoPcon::contains (double x, double y, double z) const { - return s_classTypeID; +#ifndef M_PI + constexpr double M_PI = 3.14159265358979323846; +#endif + if (!isValid ()) return false; + size_t nz = getNPlanes(); + if (z < getZPlane(0) || z > getZPlane(nz - 1)) return false; + + if (m_dPhi < 2.0 * M_PI) + { + GeoTrf::Vector2D r(x, y); + GeoTrf::Vector2D ns(std::sin(m_sPhi), -std::cos(m_sPhi)); + GeoTrf::Vector2D ne(-std::sin(m_sPhi + m_dPhi), std::cos(m_sPhi + m_dPhi)); + double ds = ns.dot(r); + double de = ne.dot(r); + bool inwedge = (m_dPhi <= M_PI) ? (ds <= 0 && de <= 0) : (ds <= 0 || de <= 0); + if (!inwedge) return false; + } + + double rr = x * x + y * y; + for (size_t k = 0; k < nz - 1; ++k) + { + double zmin = getZPlane(k); + double zmax = getZPlane(k + 1); + if (z < zmin || z > zmax || zmin == zmax) continue; + double t = (z - zmin) / (zmax - zmin); + double rmin1 = getRMinPlane(k); + double rmin2 = getRMinPlane(k + 1); + double rmin = rmin1 + (rmin2 - rmin1) * t; + double rmax1 = getRMaxPlane(k); + double rmax2 = getRMaxPlane(k + 1); + double rmax = rmax1 + (rmax2 - rmax1) * t; + if (rr <= rmax * rmax && rr >= rmin * rmin) return true; + } + return false; } void GeoPcon::addPlane (double ZPlane, double RMinPlane, double RMaxPlane) @@ -61,4 +103,3 @@ void GeoPcon::exec (GeoShapeAction *action) const { action->handlePcon(this); } - diff --git a/GeoModelCore/GeoModelKernel/src/GeoPgon.cxx b/GeoModelCore/GeoModelKernel/src/GeoPgon.cxx index 62b8d283de4f69a800b9751642dbd0ab06931e26..dd8a2d9e6bed67008163e6c693c7317f9169bb87 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoPgon.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoPgon.cxx @@ -17,51 +17,138 @@ GeoPgon::GeoPgon (double SPhi, double DPhi, unsigned int NSides) { } -GeoPgon::~GeoPgon() -{ -} - double GeoPgon::volume () const { +#ifndef M_PI + constexpr double M_PI = 3.14159265358979323846; +#endif if (!isValid ()) throw std::runtime_error ("Volume requested for incomplete polygon"); - double v = 0; - int sides = getNSides (); - double alpha = m_dPhi/sides; - double sinAlpha = sin(alpha); - - for (size_t s = 0; s < getNPlanes () - 1; s++) { - double z2 = getZPlane (s);; - double z1 = getZPlane (s + 1);; - double fRmin1 = getRMinPlane (s + 1); - double fRmin2 = getRMinPlane (s); - double fRmax1 = getRMaxPlane (s + 1); - double fRmax2 = getRMaxPlane (s); - - double b1 = (fRmax1 - fRmax2)/(z1 - z2); - double b2 = (fRmin1 - fRmin2)/(z1 - z2); - - double a1 = fRmax2 - b1 * z2; - double a2 = fRmin2 - b2 * z2; - - //v+=fabs((a1*a1-a2*a2)*(z1-z2) + (a1*b1-a2*b2)*(z1*z1-z2*z2) + (b1*b1-b2*b2)*(z1*z1*z1-z2*z2*z2)/3.); - // Equivalent which should be less sensitive to numerical precision errors: - v += fabs(z1 - z2) * ((a1 - a2) * (a1 + a2) + - (a1*b1 - a2*b2) * (z1 + z2) + - (b1 - b2) * (b1 + b2) * (z1*z1+z2*z2+z1*z2)*(1./3)); - } - v *= 0.5 * sides * sinAlpha; - return v; + double vol = 0.0; + for (size_t k = 0; k < getNPlanes() - 1; ++k) { + double z1 = getZPlane(k); + double z2 = getZPlane(k + 1); + double a1 = getRMinPlane(k); + double a2 = getRMinPlane(k + 1); + double b1 = getRMaxPlane(k); + double b2 = getRMaxPlane(k + 1); + vol += (b1*b1 + b1*b2 + b2*b2 - a1*a1 - a1*a2 - a2*a2) * (z2 - z1); + } + int nsides = getNSides(); + double dphi = getDPhi(); + if (dphi > 2.0 * M_PI) dphi = 2.0 * M_PI; + double alpha = dphi / nsides; + double sinAlpha = std::sin(alpha); + double cosHalfAlpha = std::cos(0.5 * alpha); + return std::abs(vol) * nsides * sinAlpha / (cosHalfAlpha * cosHalfAlpha * 6.0); } -const std::string & GeoPgon::type () const +void GeoPgon::extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const { - return s_classType; +#ifndef M_PI + constexpr double M_PI = 3.14159265358979323846; +#endif + if (!isValid ()) + throw std::runtime_error ("Extent requested for incomplete polygon"); + double rmin = getRMinPlane(0); + double rmax = getRMaxPlane(0); + zmin = zmax = getZPlane(0); + for (size_t k = 1; k < getNPlanes(); ++k) + { + rmin = std::min(rmin, getRMinPlane(k)); + rmax = std::max(rmax, getRMaxPlane(k)); + zmin = std::min(zmin, getZPlane(k)); + zmax = std::max(zmax, getZPlane(k)); + } + size_t nsides = getNSides(); + double dphi = getDPhi(); + if (dphi > 2.0 * M_PI) dphi = 2.0 * M_PI; + if (dphi == 2.0 * M_PI) rmin = 0.0; + double alpha = dphi / nsides; + double invCosHalfAlpha = 1. / std::cos(0.5 * alpha); + rmin *= invCosHalfAlpha; + rmax *= invCosHalfAlpha; + double phi = getSPhi(); + xmin = xmax = rmin * std::cos(phi); + ymin = ymax = rmin * std::sin(phi); + for (size_t k = 0; k <= nsides; ++k) + { + double x = rmax * std::cos(phi); + xmin = std::min(xmin, x); + xmax = std::max(xmax, x); + double y = rmax * std::sin(phi); + ymin = std::min(ymin, y); + ymax = std::max(ymax, y); + if (rmin > 0.) + { + double xx = rmin * std::cos(phi); + xmin = std::min(xmin, xx); + xmax = std::max(xmax, xx); + double yy = rmin * std::sin(phi); + ymin = std::min(ymin, yy); + ymax = std::max(ymax, yy); + } + phi += alpha; + } } -ShapeType GeoPgon::typeID () const +bool GeoPgon::contains (double x, double y, double z) const { - return s_classTypeID; + if (!isValid ()) return false; + size_t nz = getNPlanes(); + if (z < getZPlane(0) || z > getZPlane(nz - 1)) return false; + + size_t nsides = getNSides(); + double sphi = getSPhi(); + double dphi = getDPhi(); + + double dangle = dphi / nsides; // sector angle + double dhalfangle = 0.5 * dangle; + double cosHalfAngle = std::cos(dhalfangle); + double sinHalfAngle = std::sin(dhalfangle); + double cosAngle = (cosHalfAngle + sinHalfAngle) * (cosHalfAngle - sinHalfAngle); + double sinAngle = 2.0 * cosHalfAngle * sinHalfAngle; + + double r = 0.0; + double rot = -(sphi + dhalfangle); // initial rotation + double cosRot = std::cos(rot); + double sinRot = std::sin(rot); + bool inwedge = false; + for (size_t iside = 0; iside < nsides; ++iside) + { + double xrot = x * cosRot - y * sinRot; + double yrot = x * sinRot + y * cosRot; + double dista = sinHalfAngle * xrot + cosHalfAngle * yrot; + double distb = sinHalfAngle * xrot - cosHalfAngle * yrot; + if (dista >= 0.0 && distb >= 0.0) + { + r = xrot; + inwedge = true; + break; + } + double cosTmp = cosRot; + double sinTmp = sinRot; + cosRot = cosTmp * cosAngle + sinTmp * sinAngle; + sinRot = sinTmp * cosAngle - cosTmp * sinAngle; + } + if (!inwedge) return false; + + for (size_t k = 0; k < nz - 1; ++k) + { + double zmin = getZPlane(k); + double zmax = getZPlane(k + 1); + if (z < zmin || z > zmax || zmin == zmax) continue; + double t = (z - zmin) / (zmax - zmin); + double rmin1 = getRMinPlane(k); + double rmin2 = getRMinPlane(k + 1); + double rmin = rmin1 + (rmin2 - rmin1) * t; + double rmax1 = getRMaxPlane(k); + double rmax2 = getRMaxPlane(k + 1); + double rmax = rmax1 + (rmax2 - rmax1) * t; + if (r <= rmax && r >= rmin) return true; + } + return false; } void GeoPgon::addPlane (double ZPlane, double RMinPlane, double RMaxPlane) diff --git a/GeoModelCore/GeoModelKernel/src/GeoPhysVol.cxx b/GeoModelCore/GeoModelKernel/src/GeoPhysVol.cxx index 7b6161be085854086be3704e9a8d9981129714aa..fdc2568b36a1704ae9d7c3aea9d92527f4e4519d 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoPhysVol.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoPhysVol.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #include "GeoModelKernel/GeoPhysVol.h" @@ -13,21 +13,13 @@ GeoPhysVol::GeoPhysVol(const GeoLogVol* LogVol) - : GeoVPhysVol(LogVol) -{ -} + : GeoVPhysVol(LogVol) {} -GeoPhysVol::~GeoPhysVol() -{ - std::scoped_lock<std::mutex> lk(m_muxVec); - for(const GeoGraphNode* daughter : m_daughters) daughter->unref(); -} -void GeoPhysVol::add(GeoGraphNode* graphNode) -{ +void GeoPhysVol::add(GeoGraphNode* graphNode) { std::scoped_lock<std::mutex> lk(m_muxVec); - m_daughters.push_back(graphNode); - graphNode->ref(); + GeoIntrusivePtr<GeoGraphNode> nodePtr{graphNode}; + m_daughters.emplace_back(nodePtr); graphNode->dockTo(this); } @@ -199,20 +191,17 @@ unsigned int GeoPhysVol::getNChildNodes() const return m_daughters.size(); } -const GeoGraphNode * const * GeoPhysVol::getChildNode(unsigned int i) const -{ +const GeoGraphNode * const * GeoPhysVol::getChildNode(unsigned int i) const { std::scoped_lock<std::mutex> lk(m_muxVec); - return &(m_daughters[i]); + return m_daughters[i]; } -const GeoGraphNode * const * GeoPhysVol::findChildNode(const GeoGraphNode * n) const -{ +const GeoGraphNode * const * GeoPhysVol::findChildNode(const GeoGraphNode * n) const { std::scoped_lock<std::mutex> lk(m_muxVec); - std::vector<const GeoGraphNode *>::const_iterator i = std::find(m_daughters.begin(),m_daughters.end(),n); + std::vector<GeoIntrusivePtr<GeoGraphNode>>::const_iterator i = std::find(m_daughters.begin(),m_daughters.end(),n); if (i==m_daughters.end()) { return nullptr; } - else { - return &*i; - } + return (*i); + } diff --git a/GeoModelCore/GeoModelKernel/src/GeoPolyhedron.cxx b/GeoModelCore/GeoModelKernel/src/GeoPolyhedron.cxx index 1fa729636ba1de4c9bb0341994b264c187da33dc..03ad65eb05a2b45272d538e73626af74c39442e5 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoPolyhedron.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoPolyhedron.cxx @@ -85,7 +85,7 @@ ffabs (float a) * Function: Print contents of G4 polyhedron * * * ***********************************************************************/ -std::ostream & operator<< (std::ostream & ostr, const GeoFacet & facet) +std::ostream & operator<< (std::ostream & ostr, const GeoPolyhedron::GeoFacet & facet) { for (int k = 0; k < 4; k++) { diff --git a/GeoModelCore/GeoModelKernel/src/GeoSerialTransformer.cxx b/GeoModelCore/GeoModelKernel/src/GeoSerialTransformer.cxx index f97e6dc12fd762b06c35fd7d782275c203eda631..99aa495ad915867c9244b7f7fa7433d685ac4dc1 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoSerialTransformer.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoSerialTransformer.cxx @@ -5,27 +5,14 @@ #include "GeoModelKernel/GeoSerialTransformer.h" #include "GeoModelKernel/GeoNodeAction.h" -GeoSerialTransformer::GeoSerialTransformer (const GeoVPhysVol *volume, const GeoXF::Function *func, unsigned int copies) - : m_nCopies (copies) - , m_function (func->clone ()) - , m_physVol (volume) -{ - m_physVol->ref (); -} +GeoSerialTransformer::GeoSerialTransformer (const GeoVPhysVol *volume, + const GeoXF::Function *func, + unsigned int copies): + m_nCopies{copies}, + m_function{func->clone()}, + m_physVol{volume} {} -GeoSerialTransformer::~GeoSerialTransformer() -{ - m_physVol->unref (); - delete m_function; -} -void GeoSerialTransformer::exec (GeoNodeAction *action) const -{ - action->handleSerialTransformer (this); +void GeoSerialTransformer::exec(GeoNodeAction *action) const { + action->handleSerialTransformer(this); } - -const GeoXF::Function * GeoSerialTransformer::getFunction () const -{ - return m_function; -} - diff --git a/GeoModelCore/GeoModelKernel/src/GeoShape.cxx b/GeoModelCore/GeoModelKernel/src/GeoShape.cxx index 8142e0a0fb5fb1f87b4058fbc44f6518402446fc..9049e957bdea100c2682bb13a9237f34745fe216 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoShape.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoShape.cxx @@ -7,13 +7,56 @@ #include "GeoModelKernel/GeoShapeUnion.h" #include "GeoModelKernel/GeoShapeSubtraction.h" #include "GeoModelKernel/GeoShapeShift.h" +#include <cmath> +#include <cstdint> -GeoShape::GeoShape () -{ -} -GeoShape::~GeoShape() +double GeoShape::volume () const { + constexpr int npoints = 1000000; // number of random points + constexpr double expansion = 0.001; // bounding box expansion + constexpr double f = 1./4294967296.; // 2^-32 - int to double conversion + + // set up bonding box + double xmin = 0, ymin = 0, zmin = 0, xmax = 0, ymax = 0, zmax = 0; + extent(xmin, ymin, zmin, xmax, ymax, zmax); + double delx = (xmax - xmin) * expansion; + double dely = (ymax - ymin) * expansion; + double delz = (zmax - zmin) * expansion; + xmin -= delx; + ymin -= dely; + zmin -= delz; + xmax += delx; + ymax += dely; + zmax += delz; + + uint32_t y = 2463534242; // seed for random number generation + int icount = 0; // counter of inside points + for (auto i = 0; i < npoints; ++i) + { + // generate three random numbers + uint32_t x = y; + x ^= x << 13; + x ^= x >> 17; + x ^= x << 5; + double randx = x * f; + x ^= x << 13; + x ^= x >> 17; + x ^= x << 5; + double randy = x * f; + x ^= x << 13; + x ^= x >> 17; + x ^= x << 5; + double randz = x * f; + y = x; + + // calculate coordinates of random point and check its position + double px = xmin + (xmax - xmin) * randx; + double py = ymin + (ymax - ymin) * randy; + double pz = zmin + (zmax - zmin) * randz; + icount += contains(px, py, pz); + } + return (xmax - xmin) * (ymax - ymin) * (zmax -zmin) * icount / npoints; } const GeoShapeUnion & GeoShape::add (const GeoShape& shape) const @@ -39,3 +82,138 @@ const GeoShapeShift & GeoShape::operator << (const GeoTrf::Transform3D &shift) c GeoShapeShift *shiftNode = new GeoShapeShift (this, shift); return *shiftNode; } + +void GeoShape::diskExtent(double rmin, double rmax, double sphi, double dphi, + double& xmin, double& ymin, double& xmax, double& ymax) +{ +#ifndef M_PI + constexpr double M_PI = 3.14159265358979323846; +#endif + xmin = ymin =-rmax; + xmax = ymax = rmax; + if (dphi >= 2. * M_PI) return; + + double sinStart = std::sin(sphi); + double cosStart = std::cos(sphi); + double sinEnd = std::sin(sphi + dphi); + double cosEnd = std::cos(sphi + dphi); + + // get start and end quadrants, sixteen possible cases + // + // 1 | 0 + // ---+--- + // 3 | 2 + // + int icase = (cosEnd < 0) ? 1 : 0; + if (sinEnd < 0) icase += 2; + if (cosStart < 0) icase += 4; + if (sinStart < 0) icase += 8; + + switch (icase) + { + // start quadrant 0 + case 0: // start->end : 0->0 + if (sinEnd < sinStart) break; + xmin = rmin*cosEnd; + ymin = rmin*sinStart; + xmax = rmax*cosStart; + ymax = rmax*sinEnd; + break; + case 1: // start->end : 0->1 + xmin = rmax*cosEnd; + ymin = std::min(rmin*sinStart, rmin*sinEnd); + xmax = rmax*cosStart; + ymax = rmax; + break; + case 2: // start->end : 0->2 + xmin =-rmax; + ymin =-rmax; + xmax = std::max(rmax*cosStart, rmax*cosEnd); + ymax = rmax; + break; + case 3: // start->end : 0->3 + xmin =-rmax; + ymin = rmax*sinEnd; + xmax = rmax*cosStart; + ymax = rmax; + break; + // start quadrant 1 + case 4: // start->end : 1->0 + xmin =-rmax; + ymin =-rmax; + xmax = rmax; + ymax = std::max(rmax*sinStart, rmax*sinEnd); + break; + case 5: // start->end : 1->1 + if (sinEnd > sinStart) break; + xmin = rmax*cosEnd; + ymin = rmin*sinEnd; + xmax = rmin*cosStart; + ymax = rmax*sinStart; + break; + case 6: // start->end : 1->2 + xmin =-rmax; + ymin =-rmax; + xmax = rmax*cosEnd; + ymax = rmax*sinStart; + break; + case 7: // start->end : 1->3 + xmin =-rmax; + ymin = rmax*sinEnd; + xmax = std::max(rmin*cosStart, rmin*cosEnd); + ymax = rmax*sinStart; + break; + // start quadrant 2 + case 8: // start->end : 2->0 + xmin = std::min(rmin*cosStart, rmin*cosEnd); + ymin = rmax*sinStart; + xmax = rmax; + ymax = rmax*sinEnd; + break; + case 9: // start->end : 2->1 + xmin = rmax*cosEnd; + ymin = rmax*sinStart; + xmax = rmax; + ymax = rmax; + break; + case 10: // start->end : 2->2 + if (sinEnd < sinStart) break; + xmin = rmin*cosStart; + ymin = rmax*sinStart; + xmax = rmax*cosEnd; + ymax = rmin*sinEnd; + break; + case 11: // start->end : 2->3 + xmin =-rmax; + ymin = std::min(rmax*sinStart, rmax*sinEnd); + xmax = rmax; + ymax = rmax; + break; + // start quadrant 3 + case 12: // start->end : 3->0 + xmin = rmax*cosStart; + ymin =-rmax; + xmax = rmax; + ymax = rmax*sinEnd; + break; + case 13: // start->end : 3->1 + xmin = std::min(rmax*cosStart, rmax*cosEnd); + ymin =-rmax; + xmax = rmax; + ymax = rmax; + break; + case 14: // start->end : 3->2 + xmin = rmax*cosStart; + ymin =-rmax; + xmax = rmax*cosEnd; + ymax = std::max(rmin*sinStart, rmin*sinEnd); + break; + case 15: // start->end : 3->3 + if (sinEnd > sinStart) break; + xmin = rmax*cosStart; + ymin = rmax*sinEnd; + xmax = rmin*cosEnd; + ymax = rmin*sinStart; + break; + } +} diff --git a/GeoModelCore/GeoModelKernel/src/GeoShapeIntersection.cxx b/GeoModelCore/GeoModelKernel/src/GeoShapeIntersection.cxx index fccc9d3c91713f0a55a175253bf4772fc051d97c..711d2e8c7c33dde1b4bf6db3ddf1f48085ca9be2 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoShapeIntersection.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoShapeIntersection.cxx @@ -11,47 +11,34 @@ const std::string GeoShapeIntersection::s_classType = "Intersection"; const ShapeType GeoShapeIntersection::s_classTypeID = 0x00; -GeoShapeIntersection::GeoShapeIntersection (const GeoShape* A, const GeoShape* B) - : m_opA (A) - , m_opB (B) -{ - m_opA->ref (); - m_opB->ref (); -} - -GeoShapeIntersection::~GeoShapeIntersection() -{ - m_opA->unref (); - m_opB->unref (); -} +GeoShapeIntersection::GeoShapeIntersection (const GeoShape* A, + const GeoShape* B) : + m_opA (A) , m_opB (B) {} -double GeoShapeIntersection::volume () const -{ - GeoPolyhedrizeAction a; - exec(&a); - const GeoPolyhedron *poly = a.getPolyhedron(); - double vol = poly->GetVolume (); - return vol; -} -const std::string & GeoShapeIntersection::type () const -{ - return s_classType; -} -ShapeType GeoShapeIntersection::typeID () const -{ - return s_classTypeID; +double GeoShapeIntersection::volume () const { + return fVolume < 0. ? fVolume = GeoShape::volume() : fVolume.load(); } -const GeoShape* GeoShapeIntersection::getOpA () const +void GeoShapeIntersection::extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const { - return m_opA; + double xminA, yminA, zminA, xmaxA, ymaxA, zmaxA; + double xminB, yminB, zminB, xmaxB, ymaxB, zmaxB; + getOpA()->extent(xminA, yminA, zminA, xmaxA, ymaxA, zmaxA); + getOpB()->extent(xminB, yminB, zminB, xmaxB, ymaxB, zmaxB); + xmin = std::max(xminA, xminB); + ymin = std::max(yminA, yminB); + zmin = std::max(zminA, zminB); + xmax = std::min(xmaxA, xmaxB); + ymax = std::min(ymaxA, ymaxB); + zmax = std::min(zmaxA, zmaxB); } -const GeoShape* GeoShapeIntersection::getOpB () const +bool GeoShapeIntersection::contains (double x, double y, double z) const { - return m_opB; + return (getOpA()->contains(x, y, z)) ? getOpB()->contains(x, y, z) : false; } void GeoShapeIntersection::exec (GeoShapeAction *action) const diff --git a/GeoModelCore/GeoModelKernel/src/GeoShapeShift.cxx b/GeoModelCore/GeoModelKernel/src/GeoShapeShift.cxx index 3c49d7702c8276d20ef5077a6abfd7903fda2e3f..8977f9f5a044085db0da206c10a0ecc259d6e8cd 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoShapeShift.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoShapeShift.cxx @@ -1,52 +1,65 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration */ #include "GeoModelKernel/GeoShapeShift.h" #include "GeoModelKernel/GeoShapeAction.h" +#include <array> + const std::string GeoShapeShift::s_classType = "Shift"; const ShapeType GeoShapeShift::s_classTypeID = 0x03; -GeoShapeShift::GeoShapeShift (const GeoShape* A, const GeoTrf::Transform3D &X) - : m_op (A) - , m_shift (X) -{ - m_op->ref (); -} - -GeoShapeShift::~GeoShapeShift() -{ - m_op->unref (); -} - -double GeoShapeShift::volume () const -{ - return m_op->volume (); -} - -const std::string & GeoShapeShift::type () const -{ - return s_classType; +GeoShapeShift::GeoShapeShift (const GeoShape* A, const GeoTrf::Transform3D &X): + m_op{A}, m_shift{X} { + /// Check whether the given shape also a shape shift. If so then we can simply + /// take the operand of the sub shift and summarize the transformations of the two into one + if (A->refCount() > 1 && getOp()->typeID() == typeID()) { + const GeoShapeShift* subShift{static_cast<const GeoShapeShift*>(getOp())}; + m_shift = subShift->getX() * getX(); + m_op.reset(subShift->getOp()); + } } -ShapeType GeoShapeShift::typeID () const -{ - return s_classTypeID; -} -const GeoShape* GeoShapeShift::getOp () const +void GeoShapeShift::extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const { - return m_op; + const GeoShape* shape = getOp(); + const GeoTrf::Transform3D& trans = getX(); + double x_min{0.}, y_min{0.}, z_min{0.}, x_max{0.}, y_max{0.}, z_max{0.}; + shape->extent(x_min, y_min, z_min, x_max, y_max, z_max); + std::array<GeoTrf::Vector3D, 8> vv{}; + vv[0] = trans * GeoTrf::Vector3D(x_min, y_min, z_min); + vv[1] = trans * GeoTrf::Vector3D(x_max, y_min, z_min); + vv[2] = trans * GeoTrf::Vector3D(x_min, y_max, z_min); + vv[3] = trans * GeoTrf::Vector3D(x_max, y_max, z_min); + vv[4] = trans * GeoTrf::Vector3D(x_min, y_min, z_max); + vv[5] = trans * GeoTrf::Vector3D(x_max, y_min, z_max); + vv[6] = trans * GeoTrf::Vector3D(x_min, y_max, z_max); + vv[7] = trans * GeoTrf::Vector3D(x_max, y_max, z_max); + xmin = xmax = vv[0].x(); + ymin = ymax = vv[0].y(); + zmin = zmax = vv[0].z(); + for (int i = 1; i < 8; ++i) + { + xmin = std::min(xmin, vv[i].x()); + ymin = std::min(ymin, vv[i].y()); + zmin = std::min(zmin, vv[i].z()); + xmax = std::max(xmax, vv[i].x()); + ymax = std::max(ymax, vv[i].y()); + zmax = std::max(zmax, vv[i].z()); + } } -const GeoTrf::Transform3D & GeoShapeShift::getX () const -{ - return m_shift; +bool GeoShapeShift::contains (double x, double y, double z) const { + const GeoShape* shape = getOp(); + const GeoTrf::Transform3D& trans = getX(); + GeoTrf::Vector3D p = trans.inverse() * GeoTrf::Vector3D(x, y, z); + return shape->contains(p.x(), p.y(), p.z()); } -void GeoShapeShift::exec (GeoShapeAction *action) const -{ +void GeoShapeShift::exec (GeoShapeAction *action) const { action->getPath ()->push (this); action->handleShift (this); if (action->shouldTerminate ()) @@ -54,20 +67,20 @@ void GeoShapeShift::exec (GeoShapeAction *action) const action->getPath ()->pop (); return; } - + if (action->getDepthLimit ().isValid () && action->getPath ()->getLength () > action->getDepthLimit ()) { } - else - { + else + { m_op->exec(action); if (action->shouldTerminate ()) - { + { action->getPath ()->pop (); return; - } + } } action->getPath()->pop(); } diff --git a/GeoModelCore/GeoModelKernel/src/GeoShapeSubtraction.cxx b/GeoModelCore/GeoModelKernel/src/GeoShapeSubtraction.cxx index 4f3c64f74b902caf7d984b410225121afbc77a35..10a919f673bd1f148783bad251aecd3c530c3663 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoShapeSubtraction.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoShapeSubtraction.cxx @@ -11,48 +11,26 @@ const std::string GeoShapeSubtraction::s_classType = "Subtraction"; const ShapeType GeoShapeSubtraction::s_classTypeID = 0x02; -GeoShapeSubtraction::GeoShapeSubtraction (const GeoShape* A, const GeoShape* B) - : m_opA (A) - , m_opB (B) -{ - m_opA->ref (); - m_opB->ref (); -} +GeoShapeSubtraction::GeoShapeSubtraction (const GeoShape* A, const GeoShape* B): + m_opA {A}, m_opB {B} {} -GeoShapeSubtraction::~GeoShapeSubtraction() -{ - m_opA->unref (); - m_opB->unref (); -} -double GeoShapeSubtraction::volume () const -{ - GeoPolyhedrizeAction a; - exec(&a); - const GeoPolyhedron *poly = a.getPolyhedron(); - double vol = poly->GetVolume (); - return vol; +double GeoShapeSubtraction::volume () const { + return (fVolume < 0.) ? (fVolume = GeoShape::volume()) : fVolume.load(); } -const std::string & GeoShapeSubtraction::type () const +void GeoShapeSubtraction::extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const { - return s_classType; + getOpA()->extent(xmin, ymin, zmin, xmax, ymax, zmax); } -ShapeType GeoShapeSubtraction::typeID () const +bool GeoShapeSubtraction::contains (double x, double y, double z) const { - return s_classTypeID; + return (!getOpA()->contains(x, y, z)) ? false : !getOpB()->contains(x, y, z); } -const GeoShape* GeoShapeSubtraction::getOpA () const -{ - return m_opA; -} -const GeoShape* GeoShapeSubtraction::getOpB () const -{ - return m_opB; -} void GeoShapeSubtraction::exec (GeoShapeAction *action) const { diff --git a/GeoModelCore/GeoModelKernel/src/GeoShapeUnion.cxx b/GeoModelCore/GeoModelKernel/src/GeoShapeUnion.cxx index c14c4892c4fd6265494414db76b416351b619d7a..2acc7c70cc9dce8c03ad0313590b5650be5a84b0 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoShapeUnion.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoShapeUnion.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #include "GeoModelKernel/GeoShapeUnion.h" @@ -11,47 +11,32 @@ const std::string GeoShapeUnion::s_classType = "Union"; const ShapeType GeoShapeUnion::s_classTypeID = 0x01; -GeoShapeUnion::GeoShapeUnion (const GeoShape* A, const GeoShape* B) - : m_opA (A) - , m_opB (B) -{ - m_opA->ref (); - m_opB->ref (); -} +GeoShapeUnion::GeoShapeUnion (const GeoShape* A, const GeoShape* B): + m_opA{A}, m_opB{B} {} -GeoShapeUnion::~GeoShapeUnion() -{ - m_opA->unref (); - m_opB->unref (); -} double GeoShapeUnion::volume () const { - GeoPolyhedrizeAction a; - exec (&a); - const GeoPolyhedron *poly = a.getPolyhedron (); - double vol = poly->GetVolume (); - return vol; -} - -const std::string & GeoShapeUnion::type () const -{ - return s_classType; -} - -ShapeType GeoShapeUnion::typeID () const -{ - return s_classTypeID; + return (fVolume < 0.0) ? (fVolume = GeoShape::volume()) : fVolume.load(); } -const GeoShape* GeoShapeUnion::getOpA () const +void GeoShapeUnion::extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const { - return m_opA; + double xminA{0.}, yminA{0.}, zminA{0.}, xmaxA{0.}, ymaxA{0.}, zmaxA{0.}; + double xminB{0.}, yminB{0.}, zminB{0.}, xmaxB{0.}, ymaxB{0.}, zmaxB{0.}; + getOpA()->extent(xminA, yminA, zminA, xmaxA, ymaxA, zmaxA); + getOpB()->extent(xminB, yminB, zminB, xmaxB, ymaxB, zmaxB); + xmin = std::min(xminA, xminB); + ymin = std::min(yminA, yminB); + zmin = std::min(zminA, zminB); + xmax = std::max(xmaxA, xmaxB); + ymax = std::max(ymaxA, ymaxB); + zmax = std::max(zmaxA, zmaxB); } -const GeoShape* GeoShapeUnion::getOpB () const -{ - return m_opB; +bool GeoShapeUnion::contains (double x, double y, double z) const { + return getOpA()->contains(x, y, z) || getOpB()->contains(x, y, z); } void GeoShapeUnion::exec (GeoShapeAction *action) const @@ -86,4 +71,3 @@ void GeoShapeUnion::exec (GeoShapeAction *action) const } action->getPath()->pop(); } - diff --git a/GeoModelCore/GeoModelKernel/src/GeoSimplePolygonBrep.cxx b/GeoModelCore/GeoModelKernel/src/GeoSimplePolygonBrep.cxx index 3d6971dee7ab6e5442b631e53ce8f269a40e6cb8..2e9eb8de421bc200b92d103105fecdc83925fe85 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoSimplePolygonBrep.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoSimplePolygonBrep.cxx @@ -12,49 +12,59 @@ const std::string GeoSimplePolygonBrep::s_classType = "SimplePolygonBrep"; const ShapeType GeoSimplePolygonBrep::s_classTypeID = 0x20; GeoSimplePolygonBrep::GeoSimplePolygonBrep(double dz) - : m_dZ(dz) -{ -} + : m_dZ(dz){} -GeoSimplePolygonBrep::~GeoSimplePolygonBrep() -{ -} -double GeoSimplePolygonBrep::volume () const -{ + +double GeoSimplePolygonBrep::volume () const { if (!isValid()) throw std::runtime_error ("Volume requested for incomplete simple polygon brep"); - - //Todo: Cache the polygon area so we wont have to do this every time. - PolygonTriangulator pt(m_xVertices,m_yVertices); - - double area(0);//Fixme: Should be cached! - - double x1, x2, x3, y1, y2, y3; - PolygonTriangulator::Triangles::const_iterator it, itE = pt.triangles()->end(); - for (it = pt.triangles()->begin(); it!=itE; ++it) { - x1 = m_xVertices.at(it->at(0)-1); - x2 = m_xVertices.at(it->at(1)-1); - x3 = m_xVertices.at(it->at(2)-1); - y1 = m_yVertices.at(it->at(0)-1); - y2 = m_yVertices.at(it->at(1)-1); - y3 = m_yVertices.at(it->at(2)-1); - area += fabs ( -x2*y1 + x3*y1 + x1 * y2 - x3 * y2 - x1*y3 + x2*y3 );//This is actually twice the area of the triangle we are adding + int n = getNVertices(); + double area = m_xVertices[n - 1] * m_yVertices[0] - m_xVertices[0] * m_yVertices[n - 1]; + for (int k = 1; k < n; ++k) + { + area += m_xVertices[k - 1] * m_yVertices[k] - m_xVertices[k] * m_yVertices[k - 1]; } - - return area * m_dZ;//area is thus twice the area, but dZ is only half the depth, so the two factors of two cancel out. + return std::abs(area) * m_dZ; } -const std::string & GeoSimplePolygonBrep::type() const +void GeoSimplePolygonBrep::extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const { - return s_classType; + if (!isValid()) + throw std::runtime_error ("Extent requested for incomplete simple polygon brep"); + xmin = xmax = m_xVertices[0]; + ymin = ymax = m_yVertices[0]; + for (size_t k = 1; k < getNVertices(); ++k) + { + double x = m_xVertices[k]; + double y = m_yVertices[k]; + xmin = std::min(xmin, x); + xmax = std::max(xmax, x); + ymin = std::min(ymin, y); + ymax = std::max(ymax, y); + } + zmin =-m_dZ; + zmax = m_dZ; } -ShapeType GeoSimplePolygonBrep::typeID() const +bool GeoSimplePolygonBrep::contains (double x, double y, double z) const { - return s_classTypeID; + if (std::abs(z) - m_dZ > 0.0) return false; + size_t nv = getNVertices(); + bool in = false; + for (size_t i = 0, k = nv - 1; i < nv; k = i++) + { + if ((m_yVertices[i] > y) != (m_yVertices[k] > y)) + { + double ctg = (m_xVertices[k] - m_xVertices[i]) / (m_yVertices[k] - m_yVertices[i]); + in ^= (x < (y - m_yVertices[i]) * ctg + m_xVertices[i]); + } + } + return in; } + void GeoSimplePolygonBrep::addVertex(double XVertex, double YVertex) { m_xVertices.push_back(XVertex); @@ -65,4 +75,3 @@ void GeoSimplePolygonBrep::exec(GeoShapeAction *action) const { action->handleSimplePolygonBrep(this); } - diff --git a/GeoModelCore/GeoModelKernel/src/GeoTessellatedSolid.cxx b/GeoModelCore/GeoModelKernel/src/GeoTessellatedSolid.cxx index 318eea22d823f2c465ced5d923c5c8422481958f..2f7a3fabcc8cd260c234e37d23480db750570662 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoTessellatedSolid.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoTessellatedSolid.cxx @@ -1,9 +1,10 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #include "GeoModelKernel/GeoTessellatedSolid.h" #include "GeoModelKernel/GeoShapeAction.h" +#include <stdexcept> const std::string GeoTessellatedSolid::s_classType = "TessellatedSolid"; const ShapeType GeoTessellatedSolid::s_classTypeID = 0x21; @@ -12,28 +13,61 @@ GeoTessellatedSolid::GeoTessellatedSolid() { } -GeoTessellatedSolid::~GeoTessellatedSolid() -{ - for(size_t i=0; i<m_facets.size(); ++i) - m_facets[i]->unref(); -} - double GeoTessellatedSolid::volume() const { - // -- ToDo - return 0.; + if (!isValid ()) + throw std::runtime_error ("Volume requested for incomplete tessellated solid"); + double v = 0.; + for (size_t i = 0; i < getNumberOfFacets(); ++i) + { + GeoFacet* facet = getFacet(i); + GeoTrf::Vector3D e1 = facet->getVertex(2) - facet->getVertex(0); + GeoTrf::Vector3D e2 = (facet->getNumberOfVertices() == 4) ? + facet->getVertex(3) - facet->getVertex(1) : + facet->getVertex(2) - facet->getVertex(1); + v += facet->getVertex(0).dot(e1.cross(e2)); + } + if (v < 0.) + throw std::runtime_error ("Incorrect order of vertices in tessellated solid"); + return v*(1./6.); } -const std::string& GeoTessellatedSolid::type() const +void GeoTessellatedSolid::extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const { - return s_classType; + if (!isValid ()) + throw std::runtime_error ("Extent requested for incomplete tessellated solid"); + GeoFacet* facet = getFacet(0); + GeoTrf::Vector3D vertex = facet->getVertex(0); + xmin = xmax = vertex.x(); + ymin = ymax = vertex.y(); + zmin = zmax = vertex.z(); + for (size_t i = 0; i < getNumberOfFacets(); ++i) + { + facet = getFacet(i); + for (size_t k = 0; k < facet->getNumberOfVertices(); ++k) + { + vertex = facet->getVertex(k); + double x = vertex.x(); + double y = vertex.y(); + double z = vertex.z(); + xmin = std::min(xmin, x); + ymin = std::min(ymin, y); + zmin = std::min(zmin, z); + xmax = std::max(xmax, x); + ymax = std::max(ymax, y); + zmax = std::max(zmax, z); + } + } } -ShapeType GeoTessellatedSolid::typeID() const +bool GeoTessellatedSolid::contains (double x, double y, double z) const { - return s_classTypeID; + throw std::runtime_error ("GeoTessellatedSolid::contains(x,y,z) is not implemented"); + return false; } + void GeoTessellatedSolid::exec(GeoShapeAction *action) const { action->handleTessellatedSolid(this); @@ -41,13 +75,12 @@ void GeoTessellatedSolid::exec(GeoShapeAction *action) const void GeoTessellatedSolid::addFacet(GeoFacet* facet) { - facet->ref(); m_facets.push_back(facet); } - + GeoFacet* GeoTessellatedSolid::getFacet(size_t index) const { - return (index<m_facets.size() ? m_facets[index] : 0); + return (index<m_facets.size() ? m_facets.at(index) : nullptr); } size_t GeoTessellatedSolid::getNumberOfFacets() const diff --git a/GeoModelCore/GeoModelKernel/src/GeoTorus.cxx b/GeoModelCore/GeoModelKernel/src/GeoTorus.cxx index 60404bd5b1272fd57e4f6b74dd04a16c60cd6f26..717d58083cb86f0ce392077ebd7e472076a0558f 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoTorus.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoTorus.cxx @@ -4,6 +4,7 @@ #include "GeoModelKernel/GeoTorus.h" #include "GeoModelKernel/GeoShapeAction.h" +#include <cmath> const std::string GeoTorus::s_classType = "Torus"; const ShapeType GeoTorus::s_classTypeID = 0x24; @@ -11,31 +12,55 @@ const ShapeType GeoTorus::s_classTypeID = 0x24; GeoTorus::GeoTorus (double Rmin, double Rmax, double Rtor, double SPhi, double DPhi) : m_rMin (Rmin) , m_rMax (Rmax) - , m_rTor(Rtor) + , m_rTor (Rtor) , m_sPhi (SPhi) , m_dPhi (DPhi) { } -GeoTorus::~GeoTorus() -{ -} - -//## Other Operations (implementation) double GeoTorus::volume () const { - return 8.0; +#ifndef M_PI + constexpr double M_PI = 3.14159265358979323846; +#endif + return m_dPhi * M_PI * m_rTor *(m_rMax * m_rMax - m_rMin * m_rMin); } -const std::string & GeoTorus::type () const +void GeoTorus::extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const { - return s_classType; + double rmin = m_rTor - m_rMax; + double rmax = m_rTor + m_rMax; + GeoShape::diskExtent(rmin, rmax, m_sPhi, m_dPhi, xmin, ymin, xmax, ymax); + zmin =-m_rMax; + zmax = m_rMax; } -ShapeType GeoTorus::typeID () const +bool GeoTorus::contains (double x, double y, double z) const { - return s_classTypeID; +#ifndef M_PI + constexpr double M_PI = 3.14159265358979323846; +#endif + double rr = x * x + y * y; + if (std::abs(z) - m_rMax > 0.0 || rr == 0.0) return false; + double rmin = m_rTor - m_rMax; + double rmax = m_rTor + m_rMax; + if (rr > rmax * rmax || rr < rmin * rmin) return false; + + double t = (1.0 - m_rTor / std::sqrt(rr)); + double xt = x * t; + double yt = y * t; + rr = xt * xt + yt * yt + z * z; + if (rr > m_rMax * m_rMax || rr < m_rMin * m_rMin) return false; + if (m_dPhi >= 2.0 * M_PI) return true; + + GeoTrf::Vector2D r(x, y); + GeoTrf::Vector2D ns(std::sin(m_sPhi), -std::cos(m_sPhi)); + GeoTrf::Vector2D ne(-std::sin(m_sPhi + m_dPhi), std::cos(m_sPhi + m_dPhi)); + double ds = ns.dot(r); + double de = ne.dot(r); + return (m_dPhi <= M_PI) ? (ds <= 0 && de <= 0) : (ds <= 0 || de <= 0); } void GeoTorus::exec (GeoShapeAction *action) const diff --git a/GeoModelCore/GeoModelKernel/src/GeoTransform.cxx b/GeoModelCore/GeoModelKernel/src/GeoTransform.cxx index f79a07ac2697b222b54ba4b35946b04fd71a7940..d9543ee348bacca073c136faf8dca9d0e8b2196c 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoTransform.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoTransform.cxx @@ -10,21 +10,15 @@ GeoTransform::GeoTransform (const GeoTrf::Transform3D& transform) { } -GeoTransform::~GeoTransform() -{ -} -GeoTrf::Transform3D GeoTransform::getTransform(const GeoVAlignmentStore* /*store*/) const -{ +GeoTrf::Transform3D GeoTransform::getTransform(const GeoVAlignmentStore* /*store*/) const { return m_transform; } -GeoTrf::Transform3D GeoTransform::getDefTransform(const GeoVAlignmentStore* /*store*/) const -{ +const GeoTrf::Transform3D& GeoTransform::getDefTransform(const GeoVAlignmentStore* /*store*/) const { return m_transform; } -void GeoTransform::exec(GeoNodeAction *action) const -{ +void GeoTransform::exec(GeoNodeAction *action) const { action->handleTransform(this); } diff --git a/GeoModelCore/GeoModelKernel/src/GeoTrap.cxx b/GeoModelCore/GeoModelKernel/src/GeoTrap.cxx index 19c0b8eef192badb730151ed35c5fc268be12c01..99918eff3cb62f9a23106b61c38e940657c42b39 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoTrap.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoTrap.cxx @@ -23,38 +23,92 @@ GeoTrap::GeoTrap (double ZHalfLength, double Theta, double Phi, double Dydzn, do { } -GeoTrap::~GeoTrap() + +double GeoTrap::volume () const { + double dz = m_zHalfLength; + double dy1 = m_dydzn; + double dx1 = m_dxdyndzn; + double dx2 = m_dxdypdzn; + double dy2 = m_dydzp; + double dx3 = m_dxdyndzp; + double dx4 = m_dxdypdzp; + return dz * ((dx1 + dx2 + dx3 + dx4) * (dy1 + dy2) + + (dx4 + dx3 - dx2 - dx1) * (dy2 - dy1) * (1./3.)); } -double GeoTrap::volume () const +void GeoTrap::extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const { - double fDz = m_zHalfLength; - double fDy1 = m_dydzn; - double pDx1 = m_dxdyndzn; - double pDx2 = m_dxdypdzn; - double fDy2 = m_dydzp; - double pDx3 = m_dxdyndzp; - double pDx4 = m_dxdypdzp; + double dz = m_zHalfLength; + double dy1 = m_dydzn; + double dx1 = m_dxdyndzn; + double dx2 = m_dxdypdzn; + double dy2 = m_dydzp; + double dx3 = m_dxdyndzp; + double dx4 = m_dxdypdzp; + double alpha1 = m_angleydzn; + double alpha2 = m_angleydzp; + double tanTheta = std::tan(m_theta); + double dzTthetaCphi = dz * tanTheta * std::cos(m_phi); + double dzTthetaSphi = dz * tanTheta * std::sin(m_phi); + double dy1Talpha1 = dy1 * std::tan(alpha1); + double dy2Talpha2 = dy2 * std::tan(alpha2); - double fDx1 = 0.5 * (pDx1 + pDx2); - double fDx2 = 0.5 * (pDx3 + pDx4); + double x1 =-dzTthetaCphi - dy1Talpha1 - dx1; + double x2 =-dzTthetaCphi + dy1Talpha1 - dx2; + double x3 = dzTthetaCphi - dy2Talpha2 - dx3; + double x4 = dzTthetaCphi + dy2Talpha2 - dx4; + double x5 =-dzTthetaCphi - dy1Talpha1 + dx1; + double x6 =-dzTthetaCphi + dy1Talpha1 + dx2; + double x7 = dzTthetaCphi - dy2Talpha2 + dx3; + double x8 = dzTthetaCphi + dy2Talpha2 + dx4; - return 4.0 * ((fDx1 + fDx2) * (fDy1 + fDy2) * (fDz * 0.5) + - (fDx2 - fDx1) * (fDy2 - fDy1) * (fDz * (1./6))); -} + double y1 =-dzTthetaSphi - dy1; + double y2 = dzTthetaSphi - dy2; + double y3 =-dzTthetaSphi + dy1; + double y4 = dzTthetaSphi + dy2; -const std::string & GeoTrap::type () const -{ - return s_classType; + xmin = std::min(std::min(std::min(x1, x2), x3), x4); + xmax = std::max(std::max(std::max(x5, x6), x7), x8); + ymin = std::min(y1, y2); + ymax = std::max(y3, y4); + zmin =-dz; + zmax = dz; } -ShapeType GeoTrap::typeID () const +bool GeoTrap::contains (double x, double y, double z) const { - return s_classTypeID; + double z0 = z; + if (std::abs(z0) - m_zHalfLength > 0.0) return false; + + double dz = m_zHalfLength; + double dy1 = m_dydzn; + double dx1 = m_dxdyndzn; + double dx2 = m_dxdypdzn; + double dy2 = m_dydzp; + double dx3 = m_dxdyndzp; + double dx4 = m_dxdypdzp; + double alpha1 = m_angleydzn; + double alpha2 = m_angleydzp; + + double tz = 0.5 * (1.0 + z0 / dz); + double tanTheta = std::tan(m_theta); + double tanAlpha = std::tan(alpha1 + (alpha2 - alpha1) * tz); + double dy = dy1 + (dy2 - dy1) * tz; + double y0 = y - z0 * tanTheta * std::sin(m_phi); + if (std::abs(y0) - dy > 0.0) return false; + + double ty = 0.5 * (1.0 + y0 / dy); + double dxneg = dx1 + (dx3 - dx1) * tz; + double dxpos = dx2 + (dx4 - dx2) * tz; + double dx = dxneg + (dxpos - dxneg) * ty; + double x0 = x - y0 * tanAlpha - z0 * tanTheta * std::cos(m_phi); + return (std::abs(x0) - dx <= 0.0); } + void GeoTrap::exec (GeoShapeAction *action) const { action->handleTrap(this); diff --git a/GeoModelCore/GeoModelKernel/src/GeoTrd.cxx b/GeoModelCore/GeoModelKernel/src/GeoTrd.cxx index a7e9efc41103a75685e9e00bff03d8416b450633..1e0b40c0375845a32e8bd6b198975560fdc2fb17 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoTrd.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoTrd.cxx @@ -16,8 +16,6 @@ GeoTrd::GeoTrd (double XHalfLength1, double XHalfLength2, double YHalfLength1, d , m_zHalfLength (ZHalfLength) {} -GeoTrd::~GeoTrd() -{} double GeoTrd::volume () const { @@ -26,22 +24,35 @@ double GeoTrd::volume () const double fDx1 = m_xHalfLength1; double fDx2 = m_xHalfLength2; double fDy2 = m_yHalfLength2; - return 4.0 * ((fDx1 + fDx2) * (fDy1 + fDy2) * (fDz * 0.5) + - (fDx2 - fDx1) * (fDy2 - fDy1) * (fDz * (1./6))); + return 2.0 * fDz * + ((fDx1 + fDx2) * (fDy1 + fDy2) + (fDx2 - fDx1) * (fDy2 - fDy1) * (1./3.)); } -const std::string & GeoTrd::type () const +void GeoTrd::extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const { - return s_classType; + xmax = std::max(m_xHalfLength1, m_xHalfLength2); + ymax = std::max(m_yHalfLength1, m_yHalfLength2); + zmax = m_zHalfLength; + xmin = -xmax; + ymin = -ymax; + zmin = -zmax; } -ShapeType GeoTrd::typeID () const +bool GeoTrd::contains (double x, double y, double z) const { - return s_classTypeID; + if (std::abs(z) - m_zHalfLength > 0.0) return false; + double t = 0.5 * (1.0 + z / m_zHalfLength); + double dx = m_xHalfLength1 + (m_xHalfLength2 - m_xHalfLength1) * t; + double dy = m_yHalfLength1 + (m_yHalfLength2 - m_yHalfLength1) * t; + double distx = std::abs(x) - dx; + double disty = std::abs(y) - dy; + return (std::max(distx, disty) <= 0.0); } + + void GeoTrd::exec (GeoShapeAction *action) const { action->handleTrd(this); } - diff --git a/GeoModelCore/GeoModelKernel/src/GeoTube.cxx b/GeoModelCore/GeoModelKernel/src/GeoTube.cxx index cdf3c826e2c353088343e6b1703e98cde97b5b6c..b05760ed7d4a8057b74829e89313ee23780580a5 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoTube.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoTube.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #include "GeoModelKernel/GeoTube.h" @@ -24,19 +24,27 @@ GeoTube::~GeoTube() double GeoTube::volume () const { #ifndef M_PI - double M_PI = acos (-1.0); + constexpr double M_PI = 3.14159265358979323846; #endif - return 2 * M_PI * (m_rMax * m_rMax - m_rMin * m_rMin) * m_zHalfLength; + return 2.0 * M_PI * (m_rMax * m_rMax - m_rMin * m_rMin) * m_zHalfLength; } -const std::string & GeoTube::type () const +void GeoTube::extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const { - return s_classType; + xmin =-m_rMax; + ymin =-m_rMax; + zmin =-m_zHalfLength; + xmax = m_rMax; + ymax = m_rMax; + zmax = m_zHalfLength; } -ShapeType GeoTube::typeID () const +bool GeoTube::contains (double x, double y, double z) const { - return s_classTypeID; + if (std::abs(z) - m_zHalfLength > 0.0) return false; + double rr = x * x + y * y; + return ((rr <= m_rMax * m_rMax) && (rr >= m_rMin * m_rMin)); } void GeoTube::exec (GeoShapeAction *action) const diff --git a/GeoModelCore/GeoModelKernel/src/GeoTubs.cxx b/GeoModelCore/GeoModelKernel/src/GeoTubs.cxx index 1ffaf1d7dc3c34cb95d6429099a73a8bb2331ecb..0a7776b96572a35e0a41d1795a1277265b417777 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoTubs.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoTubs.cxx @@ -4,6 +4,7 @@ #include "GeoModelKernel/GeoTubs.h" #include "GeoModelKernel/GeoShapeAction.h" +#include <cmath> const std::string GeoTubs::s_classType = "Tubs"; const ShapeType GeoTubs::s_classTypeID = 0x18; @@ -17,27 +18,40 @@ GeoTubs::GeoTubs (double RMin, double RMax, double ZHalfLength, double SPhi, dou { } -GeoTubs::~GeoTubs() -{ -} double GeoTubs::volume () const { return m_dPhi * (m_rMax * m_rMax - m_rMin * m_rMin) * m_zHalfLength; } -const std::string & GeoTubs::type () const +void GeoTubs::extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const { - return s_classType; + GeoShape::diskExtent(m_rMin, m_rMax, m_sPhi, m_dPhi, xmin, ymin, xmax, ymax); + zmin =-m_zHalfLength; + zmax = m_zHalfLength; } -ShapeType GeoTubs::typeID () const +bool GeoTubs::contains (double x, double y, double z) const { - return s_classTypeID; +#ifndef M_PI + constexpr double M_PI = 3.14159265358979323846; +#endif + if (std::abs(z) - m_zHalfLength > 0.0) return false; + double rr = x * x + y * y; + if (rr > m_rMax * m_rMax || rr < m_rMin * m_rMin) return false; + if (m_dPhi >= 2.0 * M_PI) return true; + + GeoTrf::Vector2D r(x, y); + GeoTrf::Vector2D ns(std::sin(m_sPhi), -std::cos(m_sPhi)); + GeoTrf::Vector2D ne(-std::sin(m_sPhi + m_dPhi), std::cos(m_sPhi + m_dPhi)); + double ds = ns.dot(r); + double de = ne.dot(r); + return (m_dPhi <= M_PI) ? (ds <= 0 && de <= 0) : (ds <= 0 || de <= 0); } + void GeoTubs::exec (GeoShapeAction *action) const { action->handleTubs(this); } - diff --git a/GeoModelCore/GeoModelKernel/src/GeoTwistedTrap.cxx b/GeoModelCore/GeoModelKernel/src/GeoTwistedTrap.cxx index 12a9ff9f8822c531fc6e11fdba8870838ef91eff..07e3c994bb8bd2d24bfba62ac458881bee417c6f 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoTwistedTrap.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoTwistedTrap.cxx @@ -1,14 +1,15 @@ /* - Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #include "GeoModelKernel/GeoTwistedTrap.h" #include "GeoModelKernel/GeoShapeAction.h" +#include <cmath> #include <iostream> const std::string GeoTwistedTrap::s_classType = "TwistedTrap"; const ShapeType GeoTwistedTrap::s_classTypeID = 0x19; //this code should not be used by other shapes - + GeoTwistedTrap::GeoTwistedTrap(double pPhiTwist, double pDx1, @@ -16,16 +17,16 @@ GeoTwistedTrap::GeoTwistedTrap(double pPhiTwist, double pDy, double pDz ) : m_theta(0.), -m_phi(0.), -m_dy1(pDy), -m_dx1(pDx1), -m_dx2(pDx2), -m_dy2(pDy), -m_dx3(pDx1), -m_dx4(pDx2), -m_dz(pDz), -m_alph(0.), -m_phiTwist(pPhiTwist) + m_phi(0.), + m_dy1(pDy), + m_dx1(pDx1), + m_dx2(pDx2), + m_dy2(pDy), + m_dx3(pDx1), + m_dx4(pDx2), + m_dz(pDz), + m_alph(0.), + m_phiTwist(pPhiTwist) { } @@ -42,16 +43,16 @@ GeoTwistedTrap(double pPhiTwist, // twist angle double pDx4, // half x length at +pDz,+pDy double pAlph ) // tilt angle : m_theta(pTheta), -m_phi(pPhi), -m_dy1(pDy1), -m_dx1(pDx1), -m_dx2(pDx2), -m_dy2(pDy2), -m_dx3(pDx3), -m_dx4(pDx4), -m_dz(pDz), -m_alph(pAlph), -m_phiTwist(pPhiTwist) + m_phi(pPhi), + m_dy1(pDy1), + m_dx1(pDx1), + m_dx2(pDx2), + m_dy2(pDy2), + m_dx3(pDx3), + m_dx4(pDx4), + m_dz(pDz), + m_alph(pAlph), + m_phiTwist(pPhiTwist) { if ( ! ( ( m_dx1 > 2*m_CarTolerance) && ( m_dx2 > 2*m_CarTolerance) @@ -60,9 +61,9 @@ m_phiTwist(pPhiTwist) && ( m_dy1 > 2*m_CarTolerance) && ( m_dy2 > 2*m_CarTolerance) && ( m_dz > 2*m_CarTolerance) - && ( std::fabs(m_phiTwist) > 2*m_AngTolerance ) - && ( std::fabs(m_phiTwist) < SYSTEM_OF_UNITS::pi/2 ) - && ( std::fabs(m_alph) < SYSTEM_OF_UNITS::pi/2 ) + && ( std::abs(m_phiTwist) > 2*m_AngTolerance ) + && ( std::abs(m_phiTwist) < SYSTEM_OF_UNITS::pi/2 ) + && ( std::abs(m_alph) < SYSTEM_OF_UNITS::pi/2 ) && ( m_theta < SYSTEM_OF_UNITS::pi/2 && m_theta >= 0 ) ) ) { @@ -79,33 +80,78 @@ m_phiTwist(pPhiTwist) << " theta should be >= 0 and < "<< (SYSTEM_OF_UNITS::pi/2)/SYSTEM_OF_UNITS::deg << " deg"<< std::endl << " tilt angle alpha should be < "<< (SYSTEM_OF_UNITS::pi/2)/SYSTEM_OF_UNITS::deg << " deg"<<std::endl << std::endl; - + } } -GeoTwistedTrap::~GeoTwistedTrap() -{ -} - double GeoTwistedTrap::volume () const { - //not really - double cubicVolume = 2 * m_dz * ( ( m_dx1 + m_dx2 ) * m_dy1 + ( m_dx3 + m_dx4 ) * m_dy2 ); - return cubicVolume; + return m_dz * ((m_dx1 + m_dx2 + m_dx3 + m_dx4) * (m_dy1 + m_dy2) + + (m_dx4 + m_dx3 - m_dx2 - m_dx1) * (m_dy2 - m_dy1) * (1./3.)); } -const std::string & GeoTwistedTrap::type () const +void GeoTwistedTrap::extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const { - return s_classType; + double cosPhi = std::cos(m_phi); + double sinPhi = std::sin(m_phi); + double tanTheta = std::tan(m_theta); + double tanAlpha = std::tan(m_alph); + + double xmid1 = m_dy1 * tanAlpha; + double x1 = std::abs(xmid1 + m_dx1); + double x2 = std::abs(xmid1 - m_dx1); + double x3 = std::abs(xmid1 + m_dx2); + double x4 = std::abs(xmid1 - m_dx2); + double xmax1 = std::max(std::max(std::max(x1, x2), x3), x4); + double rmax1 = std::hypot(xmax1, m_dy1); + + double xmid2 = m_dy2 * tanAlpha; + double x5 = std::abs(xmid2 + m_dx3); + double x6 = std::abs(xmid2 - m_dx3); + double x7 = std::abs(xmid2 + m_dx4); + double x8 = std::abs(xmid2 - m_dx4); + double xmax2 = std::max(std::max(std::max(x5, x6), x7), x8); + double rmax2 = hypot(xmax2, m_dy2); + + double x0 = m_dz * tanTheta * cosPhi; + double y0 = m_dz * tanTheta * sinPhi; + xmin = std::min(-x0 - rmax1, x0 - rmax2); + ymin = std::min(-y0 - rmax1, y0 - rmax2); + xmax = std::max(-x0 + rmax1, x0 + rmax2); + ymax = std::max(-y0 + rmax1, y0 + rmax2); + zmin =-m_dz; + zmax = m_dz; } -ShapeType GeoTwistedTrap::typeID () const +bool GeoTwistedTrap::contains (double x, double y, double z) const { - return s_classTypeID; + double z0 = z; + if (std::abs(z0) - m_dz > 0.0) return false; + double tz = 0.5 * (1.0 + z0 / m_dz); + + double twist = -0.5 * m_phiTwist + m_phiTwist * tz; + double cosTwist = std::cos(-twist); + double sinTwist = std::sin(-twist); + double tanTheta = std::tan(m_theta); + double xc = z0 * tanTheta * std::cos(m_phi); + double yc = z0 * tanTheta * std::sin(m_phi); + + double dy = m_dy1 + (m_dy2 - m_dy1) * tz; + double y0 = sinTwist * (x - xc) + cosTwist * (y - yc); + if (std::abs(y0) - dy > 0.0) return false; + double ty = 0.5 * (1.0 + y0 / dy); + + double dxneg = m_dx1 + (m_dx3 - m_dx1) * tz; + double dxpos = m_dx2 + (m_dx4 - m_dx2) * tz; + double dx = dxneg + (dxpos - dxneg) * ty; + double x0 = cosTwist * (x - xc) - sinTwist * (y - yc) - y0 * std::tan(m_alph); + return (std::abs(x0) - dx <= 0.0); } -void GeoTwistedTrap::exec (GeoShapeAction *action) const + +void GeoTwistedTrap::exec (GeoShapeAction* action) const { - action->handleTwistedTrap(this); + action->handleTwistedTrap(this); } diff --git a/GeoModelCore/GeoModelKernel/src/GeoUnidentifiedShape.cxx b/GeoModelCore/GeoModelKernel/src/GeoUnidentifiedShape.cxx index cdae19b1b96f18adba5d4a98350b4e2ac533be8e..a5292a185b981b0fdc4fec9e730c98e5ed30c02e 100644 --- a/GeoModelCore/GeoModelKernel/src/GeoUnidentifiedShape.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoUnidentifiedShape.cxx @@ -1,6 +1,7 @@ #include "GeoModelKernel/GeoUnidentifiedShape.h" #include "GeoModelKernel/Query.h" #include "GeoModelKernel/GeoShapeAction.h" +#include <stdexcept> const std::string GeoUnidentifiedShape::_classType="UnidentifiedShape"; const ShapeType GeoUnidentifiedShape::_classTypeID=0xFFFFFFFF; @@ -18,7 +19,7 @@ GeoUnidentifiedShape::GeoUnidentifiedShape(const std::string & name, const std:: _name(name), _asciiData(asciiData) {} -// Constructor with volume: +// Constructor with volume: GeoUnidentifiedShape::GeoUnidentifiedShape(const std::string & name, const std::string & asciiData, double volume): _name(name), _asciiData(asciiData), @@ -38,7 +39,22 @@ const std::string & GeoUnidentifiedShape::asciiData() const { double GeoUnidentifiedShape::volume () const { return _volume; } - + +// Returns the bonding box of the shape +void GeoUnidentifiedShape::extent (double& xmin, double& ymin, double& zmin, + double& xmax, double& ymax, double& zmax) const +{ + throw std::runtime_error ("GeoUndefinedShape::extent is not implemented"); + xmin = ymin = zmin = xmax = ymax = zmax = 0.; +} + +// Returns true if the shape contains the point, false otherwise +bool GeoUnidentifiedShape::contains (double x, double y, double z) const +{ + throw std::runtime_error ("GeoUndefinedShape::contains(x,y,z) is not implemented"); + return false; +} + // Returns the shape type, as a string. const std::string & GeoUnidentifiedShape::type () const { return _classType; diff --git a/GeoModelCore/GeoModelKernel/src/GeoVDetectorElement.cxx b/GeoModelCore/GeoModelKernel/src/GeoVDetectorElement.cxx index dead35549118972298320bfbaa36f332114fd73c..d84ed8e2cbe9919920b12715da16648397711dfc 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoVDetectorElement.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoVDetectorElement.cxx @@ -5,10 +5,4 @@ #include "GeoModelKernel/GeoVDetectorElement.h" GeoVDetectorElement::GeoVDetectorElement (const GeoVFullPhysVol* fullPhysVol) - : m_materialGeom(fullPhysVol) -{ -} - -GeoVDetectorElement::~GeoVDetectorElement() -{ -} + : m_materialGeom(fullPhysVol){} diff --git a/GeoModelCore/GeoModelKernel/src/GeoVFullPhysVol.cxx b/GeoModelCore/GeoModelKernel/src/GeoVFullPhysVol.cxx index 598484f7970f04c462653a3912e3997e977ebb86..5cd477be53df390b5371551ade2de9bec7683aa7 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoVFullPhysVol.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoVFullPhysVol.cxx @@ -7,17 +7,8 @@ #include <string> GeoVFullPhysVol::GeoVFullPhysVol(const GeoLogVol* logVol) - : GeoVPhysVol(logVol) - , m_id(nullptr) - , m_absPosInfo(nullptr) -{ -} + : GeoVPhysVol(logVol){} -GeoVFullPhysVol::~GeoVFullPhysVol() -{ - delete m_absPosInfo; - delete m_id; -} const GeoTrf::Transform3D & GeoVFullPhysVol::getAbsoluteTransform(GeoVAlignmentStore* store) const { @@ -25,22 +16,22 @@ const GeoTrf::Transform3D & GeoVFullPhysVol::getAbsoluteTransform(GeoVAlignmentS // // // Get ready for something to go wrong: // // // - static std::string errorMessage("Full Physical Volume errroneously placed in a shared portion of a detector description graph.\nName of shared volume: "); + static std::string errorMessage("Full Physical Volume errroneously placed in a shared portion of a detector description graph.\nLogVol name of shared volume: "); // // //------------------------------------------------------------------------------------------------// - if(isShared()) throw std::runtime_error(errorMessage); + + if(isShared()) throw std::runtime_error(errorMessage+getLogVol()->getName()); std::scoped_lock<std::mutex> guard(m_mutex); - if(store==nullptr && !m_absPosInfo) m_absPosInfo = new GeoAbsPositionInfo(); + if(!store && !m_absPosInfo) m_absPosInfo = std::make_unique<GeoAbsPositionInfo>(); // // Check the cache first. If not empty, then return the cached value // - if(store==nullptr){ + if(!store) { if(m_absPosInfo->getAbsTransform()) return *m_absPosInfo->getAbsTransform(); - } - else { + } else { const GeoTrf::Transform3D* storedPos = store->getAbsPosition(this); if(storedPos!=nullptr) return *storedPos; } @@ -59,7 +50,7 @@ const GeoTrf::Transform3D & GeoVFullPhysVol::getAbsoluteTransform(GeoVAlignmentS tProd = transform * tProd; child = parent; if(child->isShared()) { - throw std::runtime_error(errorMessage); + throw std::runtime_error(errorMessage+ getLogVol()->getName() + " because of " + child->getLogVol()->getName()); } else { parent = child->getParent(); @@ -94,8 +85,7 @@ const GeoTrf::Transform3D& GeoVFullPhysVol::getCachedAbsoluteTransform(const Geo void GeoVFullPhysVol::clearPositionInfo() const { std::scoped_lock<std::mutex> guard(m_mutex); - delete m_absPosInfo; - m_absPosInfo = nullptr; + m_absPosInfo.reset(); } const GeoTrf::Transform3D& GeoVFullPhysVol::getDefAbsoluteTransform(GeoVAlignmentStore* store) const @@ -107,19 +97,18 @@ const GeoTrf::Transform3D& GeoVFullPhysVol::getDefAbsoluteTransform(GeoVAlignmen static std::string errorMessage("Full Physical Volume errroneously placed in a shared portion of a detector description graph.\nName of shared volume: "); // // //------------------------------------------------------------------------------------------------// - if(isShared()) throw std::runtime_error(errorMessage); + if(isShared()) throw std::runtime_error(errorMessage + getLogVol()->getName()); std::scoped_lock<std::mutex> guard(m_mutex); - if(store==nullptr && !m_absPosInfo) m_absPosInfo = new GeoAbsPositionInfo(); + if(!store && !m_absPosInfo) m_absPosInfo = std::make_unique<GeoAbsPositionInfo>(); // // Check the cache first. If not empty, then return the cached value // - if(store==nullptr){ + if(!store){ if(m_absPosInfo->getDefAbsTransform()) return *m_absPosInfo->getDefAbsTransform(); - } - else { + } else { const GeoTrf::Transform3D* storedPos = store->getDefAbsPosition(this); if(storedPos!=nullptr) return *storedPos; } @@ -138,7 +127,7 @@ const GeoTrf::Transform3D& GeoVFullPhysVol::getDefAbsoluteTransform(GeoVAlignmen tProd = transform * tProd; child = parent; if(child->isShared()) { - throw std::runtime_error(errorMessage); + throw std::runtime_error(errorMessage + getLogVol()->getName() + " because of " + child->getLogVol()->getName()); } else { parent = child->getParent(); @@ -169,7 +158,7 @@ const GeoTrf::Transform3D& GeoVFullPhysVol::getCachedDefAbsoluteTransform(const throw std::runtime_error("Failed to find the cached default absolute transform for " + getLogVol()->getName()); } -const std::string & GeoVFullPhysVol::getAbsoluteName () +const std::string & GeoVFullPhysVol::getAbsoluteName () const { //------------------------------------------------------------------------------------------------// // // @@ -218,7 +207,7 @@ unsigned int GeoVFullPhysVol::getId () const // // //------------------------------------------------------------------------------------------------// - if(m_id==nullptr) { + if(!m_id) { if(isShared()) throw std::runtime_error(errorMessage); // @@ -234,7 +223,7 @@ unsigned int GeoVFullPhysVol::getId () const } int index = parent->indexOf(child); - m_id = new Query<int>(parent->getIdOfChildVol(index)); + m_id = std::make_unique<Query<int>>(parent->getIdOfChildVol(index)); } return *m_id; } diff --git a/GeoModelCore/GeoModelKernel/src/GeoVPhysVol.cxx b/GeoModelCore/GeoModelKernel/src/GeoVPhysVol.cxx index 7f6660cf209b449b067e913d835b700fb66ec537..7bdcd2a8a0bd9a927bc795dd9a0c4aae2b45f4f1 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoVPhysVol.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoVPhysVol.cxx @@ -9,17 +9,8 @@ #include <stdexcept> #include <string> -GeoVPhysVol::GeoVPhysVol(const GeoLogVol* LogVol) - : m_parentPtr(nullptr) - , m_logVol(LogVol) -{ - if(m_logVol) m_logVol->ref(); -} - -GeoVPhysVol::~GeoVPhysVol() -{ - if(m_logVol) m_logVol->unref(); -} +GeoVPhysVol::GeoVPhysVol(const GeoLogVol* LogVol): + m_logVol(LogVol) {} Query<unsigned int> GeoVPhysVol::indexOf(PVConstLink daughter) const { @@ -30,19 +21,7 @@ Query<unsigned int> GeoVPhysVol::indexOf(PVConstLink daughter) const return Query<unsigned int >(); } -PVConstLink GeoVPhysVol::getParent() const -{ - if(m_parentPtr != this) return m_parentPtr; - return nullptr; -} - -const GeoLogVol* GeoVPhysVol::getLogVol() const -{ - return m_logVol; -} - -void GeoVPhysVol::apply(GeoVolumeAction *action) const -{ +void GeoVPhysVol::apply(GeoVolumeAction *action) const { int nVols(0); switch(action->getType()) { case GeoVolumeAction::TOP_DOWN: diff --git a/GeoModelCore/GeoModelKernel/src/RCBase.cxx b/GeoModelCore/GeoModelKernel/src/RCBase.cxx deleted file mode 100755 index 368cf36799fafffa56e166165ea0cce59754ea7c..0000000000000000000000000000000000000000 --- a/GeoModelCore/GeoModelKernel/src/RCBase.cxx +++ /dev/null @@ -1,30 +0,0 @@ -/* - Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration -*/ - -#include "GeoModelKernel/RCBase.h" -#include <exception> - -RCBase::RCBase() - : m_count(0) -{ -} - -RCBase::~RCBase() -{ -} - -void RCBase::ref () const -{ - m_count++; -} - -void RCBase::unref () const -{ - if (--m_count == 0) delete this; -} - -unsigned int RCBase::refCount () const -{ - return m_count.load(); -} diff --git a/GeoModelCore/GeoModelKernel/tests/testEulerAngles.cxx b/GeoModelCore/GeoModelKernel/tests/testEulerAngles.cxx new file mode 100644 index 0000000000000000000000000000000000000000..bc3ed0758417c8063efe4ab890050bbc690c79da --- /dev/null +++ b/GeoModelCore/GeoModelKernel/tests/testEulerAngles.cxx @@ -0,0 +1,97 @@ +// Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration + + + +#include "GeoModelKernel/Units.h" +#include "GeoModelKernel/GeoDefinitions.h" + +#include <stdlib.h> +#include <iostream> + +bool isIdentity(const GeoTrf::RotationMatrix3D& mat) { + for (int i = 0; i < 3; ++i) { + if (std::abs(GeoTrf::Vector3D::Unit(i).dot(mat*GeoTrf::Vector3D::Unit(i)) - 1 ) > std::numeric_limits<float>::epsilon()){ + return false; + } + } + return true; +} + +constexpr double toDeg = 1. / GeoModelKernelUnits::deg; +int main() { + for (int alpha = 0; alpha < 360 ; alpha+=15) { + GeoTrf::GeoRotation rotX{alpha*GeoModelKernelUnits::deg, 0. ,0.}; + if (std::abs(rotX.determinant() - 1) > std::numeric_limits<float>::epsilon()) { + std::cerr<<"testEulerAngles() "<<__LINE__<<" The GeoTrf::GeoRotation around the z-axis with angle "<<alpha<<" is not a rotation "<<std::endl; + return EXIT_FAILURE; + } + std::cout<<"testEulerAngles() "<<__LINE__<<" The GeoTrf::GeoRotation around the z-axis with angle "<<alpha<<" "<<std::endl<<rotX<<std::endl; + + + GeoTrf::GeoRotation rotY{0., alpha*GeoModelKernelUnits::deg, 0.}; + if (std::abs(rotY.determinant() - 1) > std::numeric_limits<float>::epsilon()) { + std::cerr<<"testEulerAngles() "<<__LINE__<<" The GeoTrf::GeoRotation around the x-axis with angle "<<alpha<<" is not a rotation "<<std::endl; + return EXIT_FAILURE; + } + std::cout<<"testEulerAngles() "<<__LINE__<<" The GeoTrf::GeoRotation around the x-axis with angle "<<alpha<<" "<<std::endl<<rotY<<std::endl; + + + GeoTrf::GeoRotation rotZ{0., 0., alpha*GeoModelKernelUnits::deg}; + if (std::abs(rotZ.determinant() - 1) > std::numeric_limits<float>::epsilon()) { + std::cerr<<"testEulerAngles() "<<__LINE__<<" The GeoTrf::GeoRotation around the z-axis with angle "<<alpha<<" is not a rotation "<<std::endl; + return EXIT_FAILURE; + } + std::cout<<"testEulerAngles() "<<__LINE__<<" The GeoTrf::GeoRotation around the z-axis with angle "<<alpha<<" "<<std::endl<<rotZ<<std::endl; + } + + for (int psi = 0; psi <= 360 ; psi+= 15) { + for (int phi = 0 ; phi <= 360; phi+= 15) { + for (int theta = 0; theta<= 360; theta+= 15) { + GeoTrf::GeoRotation rot(phi * GeoModelKernelUnits::deg, + theta*GeoModelKernelUnits::deg, + psi *GeoModelKernelUnits::deg); + if (std::abs(rot.determinant() - 1.) > std::numeric_limits<float>::epsilon()) { + std::cerr<<"testEulerAngles() "<<__LINE__<<" The rotation angles psi: "<<psi<<", phi: "<<phi<<", theta: "<<theta + <<" plugged into the GeoTrf::GeoRotation do not result into a rotation matrix "<<std::endl<<rot<< + std::endl<< GeoTrf::get3DRotMatZ(psi *GeoModelKernelUnits::deg) * + GeoTrf::get3DRotMatX(theta *GeoModelKernelUnits::deg) * + GeoTrf::get3DRotMatZ(phi *GeoModelKernelUnits::deg) <<std::endl; + return EXIT_FAILURE; + } + GeoTrf::EulerAngles angles = GeoTrf::getGeoRotationAngles(rot); + GeoTrf::GeoRotation angleRot{angles}; + if (!isIdentity(angleRot.inverse()* rot)) { + std::cout<<"testEulerAngles() "<<__LINE__<<" Injected rotation angles phi: "<<phi<<", theta: "<<theta<<" psi: "<<psi + <<std::endl<<rot<<std::endl; + std::cout<<"testEulerAngles() "<<__LINE__<<" Extracted rotation angles "<<angles.phi*toDeg<<"/" + <<angles.theta*toDeg<<"/"<<angles.psi*toDeg<<std::endl<<angleRot<<std::endl; + return EXIT_FAILURE; + } + + const GeoTrf::CoordEulerAngles coordAngles{phi*GeoModelKernelUnits::deg, + theta*GeoModelKernelUnits::deg, + psi*GeoModelKernelUnits::deg}; + const GeoTrf::GeoRotation coordRot{coordAngles}; + if (std::abs(coordRot.determinant() -1.) > std::numeric_limits<float>::epsilon()) { + std::cerr<<"testEulerAngles() "<<__LINE__<<" The rotation angles alpha: "<<psi<<", beta: "<<phi<<", gamma: "<<theta + <<" plugged into the GeoTrf::GeoRotation do not result into a rotation matrix "<<std::endl<<coordRot<<std::endl<< + GeoTrf::get3DRotMatZ(coordAngles.gamma *GeoModelKernelUnits::deg) * + GeoTrf::get3DRotMatY(coordAngles.beta *GeoModelKernelUnits::deg) * + GeoTrf::get3DRotMatX(coordAngles.alpha *GeoModelKernelUnits::deg)<<std::endl; + + } + const GeoTrf::CoordEulerAngles calcCoordAngles = GeoTrf::getCoordRotationAngles(coordRot); + const GeoTrf::GeoRotation extCoordRot{calcCoordAngles}; + if (!isIdentity(extCoordRot.inverse()* coordRot)) { + std::cout<<"testEulerAngles() "<<__LINE__<<" Injected rotation angles alpha: "<<coordAngles.alpha*toDeg + <<", beta: "<<coordAngles.beta*toDeg<<" gamma: "<<coordAngles.gamma*toDeg + <<std::endl<<coordRot<<std::endl; + std::cout<<"testEulerAngles() "<<__LINE__<<" Extracted rotation angles "<<calcCoordAngles.alpha*toDeg<<"/" + <<calcCoordAngles.beta*toDeg<<"/"<<calcCoordAngles.gamma*toDeg<<std::endl<<extCoordRot<<std::endl; + return EXIT_FAILURE; + } + } + } + } + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/GeoModelCore/GeoModelKernel/tests/testGeoIntrusivePtr.cxx b/GeoModelCore/GeoModelKernel/tests/testGeoIntrusivePtr.cxx new file mode 100644 index 0000000000000000000000000000000000000000..f740299f33a66e4fac38112979f3b3c1868bcda3 --- /dev/null +++ b/GeoModelCore/GeoModelKernel/tests/testGeoIntrusivePtr.cxx @@ -0,0 +1,70 @@ +// Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration + + +#include <GeoModelKernel/GeoFullPhysVol.h> +#include <GeoModelKernel/GeoPhysVol.h> +#include <GeoModelKernel/GeoBox.h> +#include <iostream> + + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpotentially-evaluated-expression" + +#define PRINT(OBJ) \ + std::cout<<__FILE__<<":"<<__LINE__<<" Print reference count of "<<(RCBase*)OBJ; \ + if (OBJ) std::cout<<" "<<typeid(*OBJ).name()<<" "<<OBJ->refCount(); \ + std::cout<<std::endl; + + +#define CHECKCOUNT(OBJ, EXPECT) \ + if (OBJ->refCount() != EXPECT) { \ + PRINT(OBJ); \ + std::cerr<<__FILE__<<":"<<__LINE__<<" Expect a reference count of "<<EXPECT<<std::endl; \ + return EXIT_FAILURE; \ + } \ + PRINT(OBJ); \ + std::cout<<__FILE__<<":"<<__LINE__<<" Pass ref counter check of "<<EXPECT<<std::endl; \ + +int main(int argc, char *argv[]){ + GeoMaterial* material = new GeoMaterial("Snow", 1.45); + GeoBox* uniCave = new GeoBox(100., 100., 100.); + /// Create the logical volume forklift which should increase the counters by one unit + GeoLogVol* logVol = new GeoLogVol("Forklift", uniCave, material); + + CHECKCOUNT(material, 1); + CHECKCOUNT(uniCave, 1); + + /// The logical volume should be also incremented by one unit then + GeoIntrusivePtr<GeoFullPhysVol> myPhysVol{new GeoFullPhysVol(logVol)}; + CHECKCOUNT(myPhysVol, 1); + CHECKCOUNT(logVol, 1); + /// Temporarilly create a new logical volume pointer + { + GeoIntrusivePtr<GeoLogVol> logInt{logVol}; + CHECKCOUNT(logInt, 2); + } + /// Another check that the logical volume is back to 1 + CHECKCOUNT(logVol, 1); + { + /// Derived constructor from the mother + GeoIntrusivePtr<GeoVFullPhysVol> physVol2{myPhysVol}; + CHECKCOUNT(physVol2, 2); + + /// Test move constructor + GeoIntrusivePtr<GeoVPhysVol> physVol3{std::move(physVol2)}; + CHECKCOUNT(physVol3, 2); + /// Test the copy assignment + GeoIntrusivePtr<GeoVPhysVol> physVol4{}; + physVol4 = physVol3; + CHECKCOUNT(physVol4, 3); + /// Reset + physVol4.reset(); + // We should be back to 2 + CHECKCOUNT(physVol3, 2); + /// Move assignment + physVol4 = std::move(physVol3); + CHECKCOUNT(physVol4, 2); + } + return EXIT_SUCCESS; +} +#pragma clang diagnostic pop diff --git a/GeoModelCore/README.md b/GeoModelCore/README.md index 9e28b208a9e0045ce42dccc188c8611790349111..39c0ccb3ad1d64ebd944ea10d52eb703cb4bad34 100644 --- a/GeoModelCore/README.md +++ b/GeoModelCore/README.md @@ -1,4 +1,4 @@ -[](https://gitlab.cern.ch/GeoModelDev/GeoModelCore/commits/master) +[](https://gitlab.cern.ch/GeoModelDev/GeoModelCore/commits/main) # GeoModelCore diff --git a/GeoModelExamples/CMakeLists.txt b/GeoModelExamples/CMakeLists.txt index 4f322aa26a3cb5b1d88345c6fe778b7deba9129f..2ac1024bc4281280c7395b585a9d8f9633c51e0e 100644 --- a/GeoModelExamples/CMakeLists.txt +++ b/GeoModelExamples/CMakeLists.txt @@ -6,7 +6,7 @@ ################################################################################ # Set up the project. -cmake_minimum_required( VERSION 3.1 ) +cmake_minimum_required(VERSION 3.16...3.26) project( "GeoModelExamples" VERSION 4.1.0 LANGUAGES CXX ) # Getting-started examples diff --git a/GeoModelExamples/GeoActions/CMakeLists.txt b/GeoModelExamples/GeoActions/CMakeLists.txt index 7f0efb2795bac78051a08242beaf3100158a9f10..025c7c37b893d133bb1e4e055f2d24189d06d1e9 100644 --- a/GeoModelExamples/GeoActions/CMakeLists.txt +++ b/GeoModelExamples/GeoActions/CMakeLists.txt @@ -5,7 +5,7 @@ # author: Riccardo Maria BIANCHI @ CERN - Nov, 2018 ################################################################################ -cmake_minimum_required(VERSION 3.1.0) +cmake_minimum_required(VERSION 3.16...3.26) #project(GeoActions) diff --git a/GeoModelExamples/GeoActions/README.md b/GeoModelExamples/GeoActions/README.md index da00b107317ddccea16df28041bdab9a556b049f..8eb7217b444d971b8c72b1733b53441678a14973 100644 --- a/GeoModelExamples/GeoActions/README.md +++ b/GeoModelExamples/GeoActions/README.md @@ -71,4 +71,4 @@ Now, you can **run the example** by typing: To build and run GeoModel I/O libraries, you must have a working Qt5 installation on your computer. Qt5 classes are used for I/O operations with the underlying SQLite daemon, to store/handle data, and to handle logging. -If you are not sure how to install it, please take a look at [the notes on Qt5, in the GeoModelIO repository](https://gitlab.cern.ch/GeoModelDev/GeoModelIO/blob/master/README_QT5_NOTES.md). +If you are not sure how to install it, please take a look at [the notes on Qt5, in the GeoModelIO repository](https://gitlab.cern.ch/GeoModelDev/GeoModelIO/blob/main/README_QT5_NOTES.md). diff --git a/GeoModelExamples/GeoActionsCountNodes/CMakeLists.txt b/GeoModelExamples/GeoActionsCountNodes/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..d6863e5aad4d481ce318b94da63cda1a2c31248e --- /dev/null +++ b/GeoModelExamples/GeoActionsCountNodes/CMakeLists.txt @@ -0,0 +1,32 @@ +# Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration + +################################################################################ +# Package: GeoActionsCountNodes +# author: Riccardo Maria BIANCHI @ CERN - Jan, 2023 +################################################################################ + +cmake_minimum_required(VERSION 3.1.0) + +project(GeoActionsCountingNodes) + +# Compile with C++17 +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS ON) + +if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) # when building individually + find_package( GeoModelCore REQUIRED ) + find_package( GeoModelIO REQUIRED ) +endif() + +# Find includes in current dir +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +# Populate a CMake variable with the sources +set( SRCS main.cpp CountNodesGraphAction.cxx ) + +# Tell CMake to create the helloworld executable +add_executable( countNodesAction ${SRCS} ) + +# Link all needed libraries +target_link_libraries( countNodesAction GeoModelCore::GeoModelKernel ) diff --git a/GeoModelExamples/GeoActionsCountNodes/CountNodesGraphAction.cxx b/GeoModelExamples/GeoActionsCountNodes/CountNodesGraphAction.cxx new file mode 100644 index 0000000000000000000000000000000000000000..6f3965d9cb63413b259a26ccc01e9f5047ce0905 --- /dev/null +++ b/GeoModelExamples/GeoActionsCountNodes/CountNodesGraphAction.cxx @@ -0,0 +1,59 @@ +/* + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration +*/ + +/* + * author: Riccardo.Maria.Bianchi@cern.ch, 2022 Dec + * + */ + +/* + * This example shows how to implement counting actions to count + * different types of nodes in the GeoModel tree. + * In particular, here we want to count instances of + * GeoPhysVol, GeoLogVol, GeoShape, and GeoMaterial nodes. + */ + +#include "CountNodesGraphAction.h" + +#include "GeoModelKernel/GeoBox.h" + + +// Handles a physical volume. +void CountNodesGraphAction::handlePhysVol(const GeoPhysVol* vol) { + + addPhysVol(); // increment the numbers of GeoPhysVol nodes + + // LOGVOL + const GeoLogVol* logVol = vol->getLogVol(); + addLogVol(); // increment the numbers of GeoLogVol nodes + + // MATERIAL + const GeoMaterial* mat = vol->getLogVol()->getMaterial(); + addMaterial(); // increment the numbers of GeoMaterial nodes + // SHAPE + const GeoShape* shape = vol->getLogVol()->getShape(); + addShape(); // increment the numbers of GeoShape nodes +} + +// Handles a Serial Transformer +void CountNodesGraphAction::handleSerialTransformer( + const GeoSerialTransformer* node) { + // get linked function and number of copies + const GeoXF::Function* func = node->getFunction(); + unsigned int nCopies = node->getNCopies(); + + // get linked VPhysVol volume + const GeoVPhysVol* vol = &(*(node->getVolume())); + if (dynamic_cast<const GeoPhysVol*>(vol)) { + addPhysVol(); // increment the numbers of GeoLogVol nodes + } else if (dynamic_cast<const GeoFullPhysVol*>(vol)) { + // we do not count this node in this example, but you could do it + // by adding two methods: + // - handleFullPhysVol(), to catch the GeoFullPhysVol instances in the GeoModel tree and handle them + // - addFullPhysVol(), to count the numbers of instances of GeoFullLogVol nodes + } else { + std::cout << "ERROR!!! Unknown VPhysVol type!!" << std::endl; + } +} + diff --git a/GeoModelExamples/GeoActionsCountNodes/CountNodesGraphAction.h b/GeoModelExamples/GeoActionsCountNodes/CountNodesGraphAction.h new file mode 100644 index 0000000000000000000000000000000000000000..ef81c5dfd09d5a7fa66937a16204fee414ccece0 --- /dev/null +++ b/GeoModelExamples/GeoActionsCountNodes/CountNodesGraphAction.h @@ -0,0 +1,56 @@ + +/* + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration +*/ + +/* + * author: Riccardo.Maria.Bianchi@cern.ch, 2022 Dec + * + */ + +#ifndef CountNodesGraphAction_H +#define CountNodesGraphAction_H + +// GeoModel includes +#include "GeoModelKernel/GeoGraphNode.h" +#include "GeoModelKernel/GeoNodeAction.h" + +/** + * \class GeoCountGraphAction + * + * GeoCountGraphAction acts on objects of the GeoModel tree + * and count all GeoModel nodes (GeoPhysVol, ...) and objects (GeoLogVol, + * GeoShape, ...). + * In this example, we build an action that count GeoPhysVol, GeoLogVol, + * GeoShape, and GeoMaterial nodes. + */ +class CountNodesGraphAction : public GeoNodeAction { + + public: + CountNodesGraphAction(){}; + ~CountNodesGraphAction(){}; + + // Handles a physical volume. + virtual void handlePhysVol(const GeoPhysVol *vol); + // Handles a Serial Transformer + virtual void handleSerialTransformer(const GeoSerialTransformer *obj); + + unsigned long countPhysVols() { return m_physvols; } + unsigned long countLogVols() { return m_logvols; } + unsigned long countMaterials() { return m_materials; } + unsigned long countShapes() { return m_shapes; } + + private: + unsigned addPhysVol() { return ++m_physvols; }; + unsigned addLogVol() { return ++m_logvols; }; + unsigned addShape() { return ++m_shapes; }; + unsigned addMaterial() { return ++m_materials; }; + + unsigned long m_physvols{0}; + unsigned long m_logvols{0}; + unsigned long m_materials{0}; + unsigned long m_shapes{0}; + +}; // end class + +#endif diff --git a/GeoModelExamples/GeoActionsCountNodes/main.cpp b/GeoModelExamples/GeoActionsCountNodes/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..165b88799fcf484fbae35608366340ec1366ce7d --- /dev/null +++ b/GeoModelExamples/GeoActionsCountNodes/main.cpp @@ -0,0 +1,142 @@ +// Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration + +/* + * main.cpp + * + * Author: Riccardo Maria BIANCHI @ CERN + * Created on: Jan, 2023 + * + */ + +#include <iostream> + +#include "CountNodesGraphAction.h" +#include "GeoModelKernel/GeoFullPhysVol.h" +#include "GeoModelKernel/GeoPhysVol.h" +#include "GeoModelKernel/GeoBox.h" + +#include <map> + +// Units +#include "GeoModelKernel/Units.h" +#define SYSTEM_OF_UNITS \ + GeoModelKernelUnits // so we will get, e.g., 'GeoModelKernelUnits::cm' + +int main(int argc, char* argv[]) { + //-----------------------------------------------------------------------------------// + // Define the materials that we shall use. // + // ----------------------------------------------------------------------------------// + +// Define the units +#define gr SYSTEM_OF_UNITS::gram +#define mole SYSTEM_OF_UNITS::mole +#define cm3 SYSTEM_OF_UNITS::cm3 + + // Define the chemical elements + GeoElement* Nitrogen = + new GeoElement("Nitrogen", "N", 7.0, 14.0067 * gr / mole); + GeoElement* Oxygen = + new GeoElement("Oxygen", "O", 8.0, 15.9995 * gr / mole); + GeoElement* Argon = new GeoElement("Argon", "Ar", 18.0, 39.948 * gr / mole); + GeoElement* Hydrogen = + new GeoElement("Hydrogen", "H", 1.0, 1.00797 * gr / mole); + GeoElement* Iron = new GeoElement("Iron", "Fe", 26.0, 55.847 * gr / mole); + GeoElement* Carbon = + new GeoElement("Carbon", "C", 6.0, 12.0107 * gr / mole); + GeoElement* Sillicon = + new GeoElement("Silicon", "Si", 14.0, 28.085 * gr / mole); + + // Define the materials + + double densityOfAir = 0.001214 * gr / cm3; + GeoMaterial* air = new GeoMaterial("Air", densityOfAir); + air->add(Nitrogen, 0.7494); + air->add(Oxygen, 0.2369); + air->add(Argon, 0.0129); + air->add(Hydrogen, 0.0008); + air->lock(); + + GeoMaterial* steel = new GeoMaterial("Steel", 7.9 * gr / cm3); + steel->add(Iron, 0.98); + steel->add(Carbon, 0.02); + steel->lock(); + + // Silicon 100% (Detector) + GeoMaterial* silicon = new GeoMaterial("Silicon", 2.329 * gr / cm3); + silicon->add(const_cast<GeoElement*>(Sillicon), 1.0); + silicon->lock(); + + //-----------------------------------------------------------------------------------// + // create the world volume container and + // get the 'world' volume, i.e. the root volume of the GeoModel tree + std::cout << "Creating the 'world' volume, i.e. the root volume of the " + "GeoModel tree..." + << std::endl; + const GeoBox* worldBox = + new GeoBox(1000 * SYSTEM_OF_UNITS::cm, 1000 * SYSTEM_OF_UNITS::cm, + 1000 * SYSTEM_OF_UNITS::cm); + const GeoLogVol* worldLog = new GeoLogVol("WorldLog", worldBox, air); + GeoPhysVol* world = new GeoPhysVol(worldLog); + + //-----------------------------------------------------------------------------------// + // Next make the box that describes the shape of the toy volume: // + const GeoBox* toyBox = + new GeoBox(800 * SYSTEM_OF_UNITS::cm, 800 * SYSTEM_OF_UNITS::cm, + 1000 * SYSTEM_OF_UNITS::cm); // + // Bundle this with a material into a logical volume: // + const GeoLogVol* toyLog = new GeoLogVol("ToyLog", toyBox, silicon); // + // ..And create a physical volume: // + GeoPhysVol* toyPhys = new GeoPhysVol(toyLog); // + + GeoBox* sPass = + new GeoBox(5.0 * SYSTEM_OF_UNITS::cm, 30 * SYSTEM_OF_UNITS::cm, + 30 * SYSTEM_OF_UNITS::cm); + GeoLogVol* lPass = new GeoLogVol("Passive", sPass, steel); + GeoPhysVol* pPass = new GeoPhysVol(lPass); + + GeoBox* sIPass = + new GeoBox(4 * SYSTEM_OF_UNITS::cm, 25 * SYSTEM_OF_UNITS::cm, + 25 * SYSTEM_OF_UNITS::cm); + GeoLogVol* lIPass = new GeoLogVol("InnerPassive", sIPass, air); + GeoPhysVol* pIPass = new GeoPhysVol(lIPass); + + pPass->add(pIPass); + toyPhys->add(pPass); + + //------------------------------------------------------------------------------------// + // Now insert all of this into the world... // + GeoNameTag* tag = new GeoNameTag("Toy"); // + world->add(tag); // + world->add(toyPhys); // + //------------------------------------------------------------------------------------// + + std::cout + << "\n*** Custom GeoVolumeAction example to count given types of nodes: ***" + << std::endl; + + std::map<std::string, unsigned long> mmap; + // Dump the tree volumes to a local file + std::cout + << "Inspecting the GeoModel tree starting from the input volume..." + << std::endl; + // init the graph action + CountNodesGraphAction countNodes; + world->exec(&countNodes); // visit all GeoModel nodes + + // countin nodes (can be expanded to all types of nodes) + unsigned long nphysvols = countNodes.countPhysVols(); + unsigned long nlogvols = countNodes.countLogVols(); + unsigned long nshapes = countNodes.countShapes(); + unsigned long nmaterials = countNodes.countMaterials(); + mmap["PhysVol"] = nphysvols; + mmap["Material"] = nmaterials; + mmap["LogVol"] = nlogvols; + mmap["Shapes"] = nshapes; + + for (auto& nodetype : mmap) { + std::cout << nodetype.first << ": " << nodetype.second << std::endl; + } + std::cout << "DONE. GeoModel tree inspected." << std::endl; + + return 0; +} diff --git a/GeoModelExamples/GeoFullPhysVol/CMakeLists.txt b/GeoModelExamples/GeoFullPhysVol/CMakeLists.txt index 0dafa939e9258fd32cca4c51cb61aa647ddde5ba..8168ff095aebe6ae6bae7b3d27205a6d719fb915 100644 --- a/GeoModelExamples/GeoFullPhysVol/CMakeLists.txt +++ b/GeoModelExamples/GeoFullPhysVol/CMakeLists.txt @@ -5,7 +5,7 @@ # author: Riccardo Maria BIANCHI @ CERN - Aug, 2020 ################################################################################ -cmake_minimum_required(VERSION 3.1.0) +cmake_minimum_required(VERSION 3.16...3.26) #project(GeoFullPhysVolEx) diff --git a/GeoModelExamples/GeoShapeExamples/CMakeLists.txt b/GeoModelExamples/GeoShapeExamples/CMakeLists.txt index 5fc886f4830c311cbbdc5cc290ecd3927562eecd..19bfd486d1ffc14ee531357e3394d94c318a3aaa 100644 --- a/GeoModelExamples/GeoShapeExamples/CMakeLists.txt +++ b/GeoModelExamples/GeoShapeExamples/CMakeLists.txt @@ -5,7 +5,7 @@ # author: Riccardo Maria BIANCHI @ CERN - Nov, 2018 ################################################################################ -cmake_minimum_required(VERSION 3.1.0) +cmake_minimum_required(VERSION 3.16...3.26) #project(GeoShapeExamples) diff --git a/GeoModelExamples/GeoShapeExamples/README.md b/GeoModelExamples/GeoShapeExamples/README.md index 67ec4d347b3739b4d34816c368ffa49305a16303..0629794079b2eb407f1e375ef24d94787bf5e98a 100644 --- a/GeoModelExamples/GeoShapeExamples/README.md +++ b/GeoModelExamples/GeoShapeExamples/README.md @@ -67,4 +67,4 @@ You can visualize the outcome of the example code, by opening it with VP1Light. To build and run GeoModel I/O libraries, you must have a working Qt5 installation on your computer. Qt5 classes are used for I/O operations with the underlying SQLite daemon, to store/handle data, and to handle logging. -If you are not sure how to install it, please take a look at [the notes on Qt5, in the GeoModelIO repository](https://gitlab.cern.ch/GeoModelDev/GeoModelIO/blob/master/README_QT5_NOTES.md). +If you are not sure how to install it, please take a look at [the notes on Qt5, in the GeoModelIO repository](https://gitlab.cern.ch/GeoModelDev/GeoModelIO/blob/main/README_QT5_NOTES.md). diff --git a/GeoModelExamples/GeoShapeExamples/docs/visualization.md b/GeoModelExamples/GeoShapeExamples/docs/visualization.md index 650d6c5210669800d20fe99e4b523f7f4469b2b8..9d8b257e41c87e3ad62dbb58aa2584e5b7288a47 100644 --- a/GeoModelExamples/GeoShapeExamples/docs/visualization.md +++ b/GeoModelExamples/GeoShapeExamples/docs/visualization.md @@ -1,3 +1,6 @@ + +# TODO: TO BE UPDATED!! + # Visualizing the 'GeoShiftUnion' geometry with VP1Light diff --git a/GeoModelExamples/GeoShiftUnion/CMakeLists.txt b/GeoModelExamples/GeoShiftUnion/CMakeLists.txt index 4d16de5fae91cb92dd96b6d64a24238f8ddb0dd8..71522fd448e10d3f35ad6c5ebfcb18a4abc324bd 100644 --- a/GeoModelExamples/GeoShiftUnion/CMakeLists.txt +++ b/GeoModelExamples/GeoShiftUnion/CMakeLists.txt @@ -5,7 +5,7 @@ # author: Riccardo Maria BIANCHI @ CERN - Nov, 2018 ################################################################################ -cmake_minimum_required(VERSION 3.1.0) +cmake_minimum_required(VERSION 3.16...3.26) #project(GeoShiftUnion) diff --git a/GeoModelExamples/GeoShiftUnion/README.md b/GeoModelExamples/GeoShiftUnion/README.md index d6f1cab561d92ceb6d5186af77c7e3f1c99fdcad..85e2c9ea8fea54fd66de708bd6d996ec05beacc3 100644 --- a/GeoModelExamples/GeoShiftUnion/README.md +++ b/GeoModelExamples/GeoShiftUnion/README.md @@ -62,4 +62,4 @@ You can visualize it by opening it with VP1Light. Please refer to the [Visualiza To build and run GeoModel I/O libraries, you must have a working Qt5 installation on your computer. Qt5 classes are used for I/O operations with the underlying SQLite daemon, to store/handle data, and to handle logging. -If you are not sure how to install it, please take a look at [the notes on Qt5, in the GeoModelIO repository](https://gitlab.cern.ch/GeoModelDev/GeoModelIO/blob/master/README_QT5_NOTES.md). +If you are not sure how to install it, please take a look at [the notes on Qt5, in the GeoModelIO repository](https://gitlab.cern.ch/GeoModelDev/GeoModelIO/blob/main/README_QT5_NOTES.md). diff --git a/GeoModelExamples/GeoShiftUnion/docs/visualization.md b/GeoModelExamples/GeoShiftUnion/docs/visualization.md index 650d6c5210669800d20fe99e4b523f7f4469b2b8..73ebbad67d50987ac23cb8419c999a88237e8db6 100644 --- a/GeoModelExamples/GeoShiftUnion/docs/visualization.md +++ b/GeoModelExamples/GeoShiftUnion/docs/visualization.md @@ -1,3 +1,5 @@ +# TODO: TO BE UPDATED!! + # Visualizing the 'GeoShiftUnion' geometry with VP1Light diff --git a/GeoModelExamples/GeoTessellatedSolidExamples/CMakeLists.txt b/GeoModelExamples/GeoTessellatedSolidExamples/CMakeLists.txt index 82c2df633ee7a82ae4fc26abcc937198b62627af..c5be2e21070123314d1b7ba5cd7ccbe18fafc394 100644 --- a/GeoModelExamples/GeoTessellatedSolidExamples/CMakeLists.txt +++ b/GeoModelExamples/GeoTessellatedSolidExamples/CMakeLists.txt @@ -5,7 +5,7 @@ # author: Riccardo Maria BIANCHI @ CERN - Sep, 2019 ################################################################################ -cmake_minimum_required(VERSION 3.1.0) +cmake_minimum_required(VERSION 3.16...3.26) #project(GeoTessellatedSolidExample) diff --git a/GeoModelExamples/GeoTessellatedSolidExamples/docs/visualization.md b/GeoModelExamples/GeoTessellatedSolidExamples/docs/visualization.md index 650d6c5210669800d20fe99e4b523f7f4469b2b8..4ee7f766da1c739a9295a8ffd518b21fd4921b80 100644 --- a/GeoModelExamples/GeoTessellatedSolidExamples/docs/visualization.md +++ b/GeoModelExamples/GeoTessellatedSolidExamples/docs/visualization.md @@ -1,6 +1,10 @@ + +# TODO: TO BE UPDATED!!!!!! + # Visualizing the 'GeoShiftUnion' geometry with VP1Light + If you don't have VP1Light installed on your computer: - On macOS, [you can install it with `brew`](https://github.com/ric-bianchi/homebrew-vp1light). diff --git a/GeoModelExamples/HelloDummyMaterial/CMakeLists.txt b/GeoModelExamples/HelloDummyMaterial/CMakeLists.txt index 69c45abbfe09532e60ee858a02fb1c273b8c82cd..ac6c72e7c86f82ff481239944ec965296e60d97c 100644 --- a/GeoModelExamples/HelloDummyMaterial/CMakeLists.txt +++ b/GeoModelExamples/HelloDummyMaterial/CMakeLists.txt @@ -5,7 +5,7 @@ # author: Riccardo Maria BIANCHI @ CERN - Nov, 2019 ################################################################################ -cmake_minimum_required(VERSION 3.1.0) +cmake_minimum_required(VERSION 3.16...3.26) #project(HelloDummyMaterial) diff --git a/GeoModelExamples/HelloGeo/CMakeLists.txt b/GeoModelExamples/HelloGeo/CMakeLists.txt index a7964d597ea9c82bb4ad4323ad6d99c3097025ea..ecb52b75649cd9772f276775cf4d2759972d59aa 100644 --- a/GeoModelExamples/HelloGeo/CMakeLists.txt +++ b/GeoModelExamples/HelloGeo/CMakeLists.txt @@ -5,7 +5,7 @@ # author: Riccardo Maria BIANCHI @ CERN - Nov, 2018 ################################################################################ -cmake_minimum_required(VERSION 3.1.0) +cmake_minimum_required(VERSION 3.16...3.26) # Compile with C++17 set(CMAKE_CXX_STANDARD 17) diff --git a/GeoModelExamples/HelloGeo/README.md b/GeoModelExamples/HelloGeo/README.md index c9625cf1f81865be664fa9c2ded97d5080bb4784..ad7e50e5193bb9188398a2cc75f0bab95f4042ad 100644 --- a/GeoModelExamples/HelloGeo/README.md +++ b/GeoModelExamples/HelloGeo/README.md @@ -13,38 +13,9 @@ The example program: * loops over all the RootVolume's children volumes (GeoPhysVol and GeoFullPhysVol instances), printing the name of the GeoLogVol associated to them -## Dependencies - -### Install Qt5 - -To build and run GeoModel I/O libraries, you must have a working Qt5 installation on your computer. -If you are not sure how to install it, please take a look at the Appendix, below. - -### GeoModelCore - -```bash -git clone ssh://git@gitlab.cern.ch:7999/GeoModelDev/GeoModelCore.git -mkdir build_gmcore -cd build_gmcore -cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=RelWithDebInfo ../GeoModelCore -make -j 4 -make install -cd .. -``` - - - ## Build -From your work folder: - -```bash -git clone ssh://git@gitlab.cern.ch:7999/GeoModelDev/GeoModelExamples.git -mkdir build_hellogeo -cd build_hellogeo -cmake -DCMAKE_INSTALL_PREFIX=../install ../GeoModelExamples/HelloGeo/ -make -j4 -``` +To build the GeoModelExamples please refer to the documentation at [GeoModel website](https://geomodel.web.cern.ch/home/) ## Run @@ -53,13 +24,3 @@ Now, you can **run the example** by typing: ```bash ./hellogeo ``` - ----- - -## Appendix - -### Notes on Qt5 - -To build and run GeoModel I/O libraries, you must have a working Qt5 installation on your computer. Qt5 classes are used for I/O operations with the underlying SQLite daemon, to store/handle data, and to handle logging. - -If you are not sure how to install it, please take a look at [the notes on Qt5, in the GeoModelIO repository](https://gitlab.cern.ch/GeoModelDev/GeoModelIO/blob/master/README_QT5_NOTES.md). diff --git a/GeoModelExamples/HelloGeoRead/CMakeLists.txt b/GeoModelExamples/HelloGeoRead/CMakeLists.txt index 59f098de3ae233c4a5885fce0502e24580ff5269..a6d60624553baa2ae4b94a5b655fa8917629063b 100644 --- a/GeoModelExamples/HelloGeoRead/CMakeLists.txt +++ b/GeoModelExamples/HelloGeoRead/CMakeLists.txt @@ -5,9 +5,9 @@ # author: Riccardo Maria BIANCHI @ CERN - Nov, 2018 ################################################################################ -cmake_minimum_required(VERSION 3.1.0) +cmake_minimum_required(VERSION 3.16...3.26) -#project(HelloGeoRead) +project(HelloGeoRead) # Compile with C++17 set(CMAKE_CXX_STANDARD 17) @@ -24,10 +24,16 @@ endif() set(CMAKE_INCLUDE_CURRENT_DIR ON) # Populate a CMake variable with the sources -set(SRCS main.cpp ) +set(SRCS1 main1.cpp ) +set(SRCS2 main2.cpp ) +set(SRCS3 main3.cpp ) # Tell CMake to create the helloworld executable -add_executable( hellogeoRead ${SRCS} ) +add_executable( hellogeoRead_1 ${SRCS1} ) +add_executable( hellogeoRead_2 ${SRCS2} ) +add_executable( hellogeoRead_3 ${SRCS3} ) # Link all needed libraries -target_link_libraries( hellogeoRead GeoModelIO::GeoModelRead GeoModelCore::GeoModelKernel) +target_link_libraries( hellogeoRead_1 GeoModelIO::GeoModelRead GeoModelCore::GeoModelKernel GeoModelIO::GeoModelIOHelpers GeoModelIO::GeoModelWrite) +target_link_libraries( hellogeoRead_2 GeoModelIO::GeoModelRead GeoModelCore::GeoModelKernel GeoModelIO::GeoModelIOHelpers GeoModelIO::GeoModelWrite) +target_link_libraries( hellogeoRead_3 GeoModelIO::GeoModelRead GeoModelCore::GeoModelKernel) diff --git a/GeoModelExamples/HelloGeoRead/README.md b/GeoModelExamples/HelloGeoRead/README.md index 8bfbbf64e13d6c6c767c9eb9193ec744f5ff8e7e..e1573cdf0a984244deb2d1e0dcdb4ecd7acac60e 100644 --- a/GeoModelExamples/HelloGeoRead/README.md +++ b/GeoModelExamples/HelloGeoRead/README.md @@ -13,70 +13,21 @@ The example program: The example program uses many of the GeoModel packages. -## Dependencies - -### Install Qt5 - -To build and run GeoModel libraries, you must have a working Qt5 installation on your computer. -If you are not sure how to install it, please take a look at the Appendix on Qt5, below. - -### Build GeoModelCore - -```bash -git clone ssh://git@gitlab.cern.ch:7999/GeoModelDev/GeoModelCore.git -mkdir build_gmcore -cd build_gmcore -cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=RelWithDebInfo ../GeoModelCore -make -j 4 -make install -``` - -### Build GeoModelIO - -```bash -git clone ssh://git@gitlab.cern.ch:7999/GeoModelDev/GeoModelIO.git -mkdir build_gmio -cd build_gmio -cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=RelWithDebInfo ../GeoModelIO -make -j 4 -make install -``` - ## Build -From your work folder: - -```bash -git clone ssh://git@gitlab.cern.ch:7999/GeoModelDev/GeoModelExamples.git -mkdir build_hellogeoRead -cd build_hellogeoRead -cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=RelWithDebInfo ../GeoModelExamples/HelloGeoRead -make -j4 -make install -``` +To build the GeoModelExamples please refer to the documentation at [GeoModel website](https://geomodel.web.cern.ch/home/) ## Run Get sample geometry data to play with: ```bash -wget https://atlas-vp1.web.cern.ch/atlas-vp1/doc_new/sample_datafiles/geometry/geometry-ATLAS-R2-2015-03-01-00.db -ln -s $PWD/geometry-ATLAS-R2-2015-03-01-00.db ../geometry.db +wget https://geomodel.web.cern.ch/atlas-geometry-data/geometry-ATLAS-R3S-2021-03-02-00.db +ln -s $PWD/geometry-ATLAS-R3S-2021-03-02-00.db ../geometry.db ``` Now, you can run the example by typing: ```bash -./hellogeoRead +./hellogeoRead geometry.db ``` - - - ---- - -## Appendix - -### Notes on Qt5 - -To build and run GeoModel I/O libraries, you must have a working Qt5 installation on your computer. Qt5 classes are used for I/O operations with the underlying SQLite daemon, to store/handle data, and to handle logging. - -If you are not sure how to install it, please take a look at [the notes on Qt5, in the GeoModelIO repository](https://gitlab.cern.ch/GeoModelDev/GeoModelIO/blob/master/README_QT5_NOTES.md). diff --git a/GeoModelExamples/HelloGeoRead/main.cpp b/GeoModelExamples/HelloGeoRead/main.cpp deleted file mode 100644 index 00765ec207682ef11689d1d56d713b07442c1636..0000000000000000000000000000000000000000 --- a/GeoModelExamples/HelloGeoRead/main.cpp +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration - -/* - * HelloGeo.cpp - * - * Author: Riccardo Maria BIANCHI @ CERN - * Created on: Nov, 2018 - * - */ - -// GeoModel includes -#include "GeoModelDBManager/GMDBManager.h" -#include "GeoModelRead/ReadGeoModel.h" -#include "GeoModelKernel/GeoBox.h" -#include "GeoModelKernel/GeoPhysVol.h" -#include "GeoModelKernel/GeoFullPhysVol.h" -#include "GeoModelKernel/GeoNameTag.h" - -// C++ includes -#include <iostream> -#include <fstream> -#include <cstdlib> // EXIT_FAILURE - - -// Units -#include "GeoModelKernel/Units.h" -#define SYSTEM_OF_UNITS GeoModelKernelUnits // so we will get, e.g., 'GeoModelKernelUnits::cm' - - -GeoPhysVol* createTheWorld(GeoPhysVol* world) -{ - if (world == nullptr) - { - //-----------------------------------------------------------------------------------// - // Define the materials that we shall use. // - // ----------------------------------------------------------------------------------// - - // Define the units - #define gr SYSTEM_OF_UNITS::gram - #define mole SYSTEM_OF_UNITS::mole - #define cm3 SYSTEM_OF_UNITS::cm3 - - // Define the chemical elements - GeoElement* Nitrogen = new GeoElement ("Nitrogen" ,"N" , 7.0 , 14.0067 *gr/mole); - GeoElement* Oxygen = new GeoElement ("Oxygen" ,"O" , 8.0 , 15.9995 *gr/mole); - GeoElement* Argon = new GeoElement ("Argon" ,"Ar" , 18.0 , 39.948 *gr/mole); - GeoElement* Hydrogen = new GeoElement ("Hydrogen" ,"H" , 1.0 , 1.00797 *gr/mole); - - // Define the materials - double densityOfAir=0.001214 *gr/cm3; - GeoMaterial *air = new GeoMaterial("Air", densityOfAir); - air->add(Nitrogen , 0.7494); - air->add(Oxygen, 0.2369); - air->add(Argon, 0.0129); - air->add(Hydrogen, 0.0008); - air->lock(); - - const GeoBox* worldBox = new GeoBox(1000*SYSTEM_OF_UNITS::cm, 1000*SYSTEM_OF_UNITS::cm, 1000*SYSTEM_OF_UNITS::cm); - const GeoLogVol* worldLog = new GeoLogVol("WorldLog", worldBox, air); - world = new GeoPhysVol(worldLog); - } - return world; -} - - - -int main(int argc, char *argv[]) -{ - - if(argc != 2) - { - fprintf(stderr, "\nERROR!\nusage: %s input.db\n\n", argv[0]); - return 1; - } - // Get the input SQLite '.db' file containing the geometry - std::string line; - std::string fileName; - fileName = argv[1]; - std::cout << "Using this SQLite '.db' file:" << fileName << std::endl; - - - // check if DB file exists. If not, return. - // FIXME: TODO: this check should go in the 'GMDBManager' constructor. - std::ifstream infile(fileName.c_str()); - if ( ! infile.good() ) { - std::cout << "\n\tERROR!! A '" << fileName << "' file does not exist!! Please, check the path of the input file before running this program. Exiting..."; - exit(EXIT_FAILURE); - } - infile.close(); - - - // GET GEOMETRY FROM LOCAL DB - - - - // open the DB - GMDBManager* db = new GMDBManager(fileName); - /* Open database */ - if (db->checkIsDBOpen()) { - std::cout << "OK! Database is open!\n"; - } - else { - std::cout << "Database is not open!\n"; - // return; - throw; - } - - // -- testing the input database -// std::cout << "Printing the list of all GeoMaterial nodes" << std::endl; -// db->printAllMaterials(); -// std::cout << "Printing the list of all GeoElement nodes" << std::endl; -// db->printAllElements(); - - /* setup the GeoModel reader */ - GeoModelIO::ReadGeoModel geoReader = GeoModelIO::ReadGeoModel(db); - std::cout << "OK! ReadGeoModel is set." << std::endl; - - - /* build the GeoModel geometry */ - GeoPhysVol* dbPhys = geoReader.buildGeoModel(); // builds the whole GeoModel tree in memory - std::cout << "ReadGeoModel::buildGeoModel() done." << std::endl; - - std::cout << "Reading records from the imported geometry DB file..." << std::endl; - geoReader.printDBTable("SerialIdentifiers"); - geoReader.printDBTable("IdentifierTags"); - - - // create the world volume container and - // get the 'world' volume, i.e. the root volume of the GeoModel tree - std::cout << "Getting the 'world' GeoPhysVol, i.e. the root volume of the GeoModel tree" << std::endl; - GeoPhysVol* world = createTheWorld(dbPhys); - std::cout << "Getting the GeoLogVol used by the 'world' volume" << std::endl; - const GeoLogVol* logVol = world->getLogVol(); - std::cout << "'world' GeoLogVol name: " << logVol->getName() << std::endl; - std::cout << "'world' GeoMaterial name: " << logVol->getMaterial()->getName() << std::endl; - - - // --- testing the imported Geometry - - // get number of children volumes - unsigned int nChil = world->getNChildVols(); - std:: cout << "'world' number of children: " << nChil << std::endl; - - // loop over all children nodes - std::cout << "Looping over all 'volume' children (i.e., GeoPhysVol and GeoFullPhysVol)..." << std::endl; - for (unsigned int idx=0; idx<nChil; ++idx) { - PVConstLink nodeLink = world->getChildVol(idx); - - if ( dynamic_cast<const GeoVPhysVol*>( &(*( nodeLink ))) ) { - - std::cout << "\t" << "the child n. " << idx << " "; - const GeoVPhysVol *childVolV = &(*( nodeLink )); - - if ( dynamic_cast<const GeoPhysVol*>(childVolV) ) { - const GeoPhysVol* childVol = dynamic_cast<const GeoPhysVol*>(childVolV); - std::cout << "is a GeoPhysVol, whose GeoLogVol name is: " << childVol->getLogVol()->getName(); - std::cout<< " and it has "<<childVol->getNChildVols()<<" child volumes" << std::endl; - } - else if ( dynamic_cast<const GeoFullPhysVol*>(childVolV) ) { - const GeoFullPhysVol* childVol = dynamic_cast<const GeoFullPhysVol*>(childVolV); - std::cout << "is a GeoFullPhysVol, whose GeoLogVol name is: " << childVol->getLogVol()->getName(); - std::cout<< " and it has "<<childVol->getNChildVols()<<" child volumes" << std::endl; - } - } - else if ( dynamic_cast<const GeoNameTag*>( &(*( nodeLink ))) ) { - std::cout << "\t" << "the child n. " << idx << " is a GeoNameTag" << std::endl; - const GeoNameTag *childVol = dynamic_cast<const GeoNameTag*>(&(*( nodeLink ))); - std::cout << "\t\t GeoNameTag's name: " << childVol->getName() << std::endl; - } - else if ( dynamic_cast<const GeoMaterial*>( &(*( nodeLink ))) ) { - std::cout << "\t" << "the child n. " << idx << " is a GeoMaterial" << std::endl; - const GeoMaterial *childVol = dynamic_cast<const GeoMaterial*>(&(*( nodeLink ))); - std::cout << "\t\t GeoMaterial's name: " << childVol->getName() << std::endl; - std::cout << "\t\t GeoMaterial's number of elements: " << childVol->getNumElements() << std::endl; - } - } - - - std::cout << "Everything done." << std::endl; - - // return app.exec(); - return 0; -} diff --git a/GeoModelExamples/HelloGeoRead/main1.cpp b/GeoModelExamples/HelloGeoRead/main1.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0d037fd5cf6c9b42c3997fce915ded31b25c80b4 --- /dev/null +++ b/GeoModelExamples/HelloGeoRead/main1.cpp @@ -0,0 +1,116 @@ +// Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration + +/* + * HelloGeoRead_1 + * + * Author: Riccardo Maria BIANCHI @ CERN + * Created on: Nov, 2018 + * Updated on: Oct, 2023 + * + */ + +// GeoModel includes +#include "GeoModelIOHelpers/GMIO.h" + +#include "GeoModelKernel/GeoBox.h" +#include "GeoModelKernel/GeoFullPhysVol.h" +#include "GeoModelKernel/GeoNameTag.h" +#include "GeoModelKernel/GeoPhysVol.h" +#include "GeoModelRead/ReadGeoModel.h" + +// C++ includes +#include <cstdlib> // EXIT_FAILURE +#include <fstream> +#include <iostream> + + +int main(int argc, char* argv[]) { + if (argc != 2) { + fprintf(stderr, "\nERROR!\nUsage: %s <geometry.db>\n\n", argv[0]); + return 1; + } + + // Get from command-line the input SQLite '.db' file containing the geometry + std::string fileName; + fileName = argv[1]; + std::cout << "Using this SQLite '.db' file:" << fileName << std::endl; + + + // Get the 'world' volume from the GeoModel DB + std::cout << "Picking the 'World' volume from the geometry DB file..." + << std::endl; + const GeoVPhysVol *world = GeoModelIO::IO::loadDB(fileName); + if(world == nullptr) { + std::cout << "---ERROR! 'World' is a 'nullptr'! exiting...\n\n"; + exit(1); + } else { + std::cout << "'World' volume loaded." << std::endl; + } + + // --- Reading the properties of the 'world' volume retrieved from the .db file + std::cout << "Getting the GeoLogVol used by the 'world' volume" + << std::endl; + const GeoLogVol* logVol = world->getLogVol(); + std::cout << "'world' GeoLogVol name: " << logVol->getName() << std::endl; + std::cout << "'world' GeoMaterial name: " + << logVol->getMaterial()->getName() << std::endl; + + // --- Reading the imported Geometry + + // get number of children volumes + unsigned int nChil = world->getNChildVols(); + std::cout << "'world' number of children: " << nChil << std::endl; + + // loop over all children nodes + std::cout << "Looping over all 'volume' children (i.e., GeoPhysVol and " + "GeoFullPhysVol)..." + << std::endl; + for (unsigned int idx = 0; idx < nChil; ++idx) { + PVConstLink nodeLink = world->getChildVol(idx); + + if (dynamic_cast<const GeoVPhysVol*>(&(*(nodeLink)))) { + std::cout << "\t" + << "the child n. " << idx << " "; + const GeoVPhysVol* childVolV = &(*(nodeLink)); + + if (dynamic_cast<const GeoPhysVol*>(childVolV)) { + const GeoPhysVol* childVol = + dynamic_cast<const GeoPhysVol*>(childVolV); + std::cout << "is a GeoPhysVol, whose GeoLogVol name is: " + << childVol->getLogVol()->getName(); + std::cout << " and it has " << childVol->getNChildVols() + << " child volumes" << std::endl; + } else if (dynamic_cast<const GeoFullPhysVol*>(childVolV)) { + const GeoFullPhysVol* childVol = + dynamic_cast<const GeoFullPhysVol*>(childVolV); + std::cout << "is a GeoFullPhysVol, whose GeoLogVol name is: " + << childVol->getLogVol()->getName(); + std::cout << " and it has " << childVol->getNChildVols() + << " child volumes" << std::endl; + } + } else if (dynamic_cast<const GeoNameTag*>(&(*(nodeLink)))) { + std::cout << "\t" + << "the child n. " << idx << " is a GeoNameTag" + << std::endl; + const GeoNameTag* childVol = + dynamic_cast<const GeoNameTag*>(&(*(nodeLink))); + std::cout << "\t\t GeoNameTag's name: " << childVol->getName() + << std::endl; + } else if (dynamic_cast<const GeoMaterial*>(&(*(nodeLink)))) { + std::cout << "\t" + << "the child n. " << idx << " is a GeoMaterial" + << std::endl; + const GeoMaterial* childVol = + dynamic_cast<const GeoMaterial*>(&(*(nodeLink))); + std::cout << "\t\t GeoMaterial's name: " << childVol->getName() + << std::endl; + std::cout << "\t\t GeoMaterial's number of elements: " + << childVol->getNumElements() << std::endl; + } + } + + std::cout << "Everything done." << std::endl; + + // return app.exec(); + return 0; +} diff --git a/GeoModelExamples/HelloGeoRead/main2.cpp b/GeoModelExamples/HelloGeoRead/main2.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3c34d9c2a9019fd4fdf96935f1626084621f33c1 --- /dev/null +++ b/GeoModelExamples/HelloGeoRead/main2.cpp @@ -0,0 +1,126 @@ +// Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration + +/* + * HelloGeoRead_2 + * + * Author: Riccardo Maria BIANCHI @ CERN + * Created on: Nov, 2018 + * Updated on: Oct, 2023 + * + */ + +// GeoModel includes +#include "GeoModelIOHelpers/GMIO.h" + +#include "GeoModelKernel/GeoBox.h" +#include "GeoModelKernel/GeoFullPhysVol.h" +#include "GeoModelKernel/GeoNameTag.h" +#include "GeoModelKernel/GeoPhysVol.h" +#include "GeoModelRead/ReadGeoModel.h" + +// C++ includes +#include <cstdlib> // EXIT_FAILURE +#include <fstream> +#include <iostream> + + +int main(int argc, char* argv[]) { + if (argc != 2) { + fprintf(stderr, "\nERROR!\nUsage: %s <geometry.db>\n\n", argv[0]); + return 1; + } + + // Get from command-line the input SQLite '.db' file containing the geometry + std::string line; + std::string fileName; + fileName = argv[1]; + std::cout << "Using this SQLite '.db' file:" << fileName << std::endl; + + // Get a reader to explore/print the tables in the GeoModel DB + GeoModelIO::ReadGeoModel geoReader = GeoModelIO::IO::getReaderDB(fileName); + std::cout << "Reading records from the imported geometry DB file..." + << std::endl; + geoReader.printDBTable("NameTags"); + geoReader.printDBTable("Elements"); + + + // Get the 'world' volume from the GeoModel DB + std::cout << "Picking the 'World' volume from the geometry DB file..." + << std::endl; + const GeoVPhysVol *world = GeoModelIO::IO::loadDB(fileName); + std::cout << "'World' volume loaded." << std::endl; + if(world == nullptr) { + std::cout << "---ERROR! 'World' is a 'nullptr'! exiting...\n\n"; + exit(1); + } else { + std::cout << "'World' volume loaded." << std::endl; + } + + + // --- Reading the properties of the 'world' volume retrieved from the .db file + std::cout << "Getting the GeoLogVol used by the 'world' volume" + << std::endl; + const GeoLogVol* logVol = world->getLogVol(); + std::cout << "'world' GeoLogVol name: " << logVol->getName() << std::endl; + std::cout << "'world' GeoMaterial name: " + << logVol->getMaterial()->getName() << std::endl; + + // --- Reading the imported Geometry + + // get number of children volumes + unsigned int nChil = world->getNChildVols(); + std::cout << "'world' number of children: " << nChil << std::endl; + + // loop over all children nodes + std::cout << "Looping over all 'volume' children (i.e., GeoPhysVol and " + "GeoFullPhysVol)..." + << std::endl; + for (unsigned int idx = 0; idx < nChil; ++idx) { + PVConstLink nodeLink = world->getChildVol(idx); + + if (dynamic_cast<const GeoVPhysVol*>(&(*(nodeLink)))) { + std::cout << "\t" + << "the child n. " << idx << " "; + const GeoVPhysVol* childVolV = &(*(nodeLink)); + + if (dynamic_cast<const GeoPhysVol*>(childVolV)) { + const GeoPhysVol* childVol = + dynamic_cast<const GeoPhysVol*>(childVolV); + std::cout << "is a GeoPhysVol, whose GeoLogVol name is: " + << childVol->getLogVol()->getName(); + std::cout << " and it has " << childVol->getNChildVols() + << " child volumes" << std::endl; + } else if (dynamic_cast<const GeoFullPhysVol*>(childVolV)) { + const GeoFullPhysVol* childVol = + dynamic_cast<const GeoFullPhysVol*>(childVolV); + std::cout << "is a GeoFullPhysVol, whose GeoLogVol name is: " + << childVol->getLogVol()->getName(); + std::cout << " and it has " << childVol->getNChildVols() + << " child volumes" << std::endl; + } + } else if (dynamic_cast<const GeoNameTag*>(&(*(nodeLink)))) { + std::cout << "\t" + << "the child n. " << idx << " is a GeoNameTag" + << std::endl; + const GeoNameTag* childVol = + dynamic_cast<const GeoNameTag*>(&(*(nodeLink))); + std::cout << "\t\t GeoNameTag's name: " << childVol->getName() + << std::endl; + } else if (dynamic_cast<const GeoMaterial*>(&(*(nodeLink)))) { + std::cout << "\t" + << "the child n. " << idx << " is a GeoMaterial" + << std::endl; + const GeoMaterial* childVol = + dynamic_cast<const GeoMaterial*>(&(*(nodeLink))); + std::cout << "\t\t GeoMaterial's name: " << childVol->getName() + << std::endl; + std::cout << "\t\t GeoMaterial's number of elements: " + << childVol->getNumElements() << std::endl; + } + } + + std::cout << "Everything done." << std::endl; + + // return app.exec(); + return 0; +} diff --git a/GeoModelExamples/HelloGeoRead/main3.cpp b/GeoModelExamples/HelloGeoRead/main3.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f71b81f680580dbc11103ae2d62eab6cac0c0ff5 --- /dev/null +++ b/GeoModelExamples/HelloGeoRead/main3.cpp @@ -0,0 +1,149 @@ +// Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration + +/* + * HelloGeoRead_3 + * + * Author: Riccardo Maria BIANCHI @ CERN + * Created on: Nov, 2018 + * Updated on: Oct, 2023 + * + */ + +// GeoModel includes +#include "GeoModelDBManager/GMDBManager.h" + +#include "GeoModelKernel/GeoBox.h" +#include "GeoModelKernel/GeoFullPhysVol.h" +#include "GeoModelKernel/GeoNameTag.h" +#include "GeoModelKernel/GeoPhysVol.h" +#include "GeoModelRead/ReadGeoModel.h" + +// C++ includes +#include <cstdlib> // EXIT_FAILURE +#include <fstream> +#include <iostream> + + +int main(int argc, char* argv[]) { + if (argc != 2) { + fprintf(stderr, "\nERROR!\nUsage: %s <geometry.db>\n\n", argv[0]); + return 1; + } + + // Get from command-line the input SQLite '.db' file containing the geometry + std::string line; + std::string fileName; + fileName = argv[1]; + std::cout << "Using this SQLite '.db' file:" << fileName << std::endl; + + + // check if DB file exists. If not, return. + std::ifstream inputfile(fileName.c_str()); + if (!inputfile.good()) { + std::cout << "\n\tERROR!! A '" << fileName + << "' file does not exist!! Please, check the path of the " + "input file before running this program. Exiting..."; + exit(EXIT_FAILURE); + } + inputfile.close(); + + // open the DB + GMDBManager* db = new GMDBManager(fileName); + /* Open database */ + if (db->checkIsDBOpen()) { + std::cout << "OK! Database is open!\n"; + } else { + std::cout << "Database is not open!\n"; + // return; + throw; + } + + /* testing the input database */ + std::cout << "Reading records from the database..." << std::endl; + std::cout << "Printing the list of all GeoMaterial nodes" << std::endl; + db->printAllMaterials(); + std::cout << "Printing the list of all GeoElement nodes" << std::endl; + db->printAllElements(); + + /* set the GeoModel reader */ + GeoModelIO::ReadGeoModel geoReader = GeoModelIO::ReadGeoModel(db); + std::cout << "OK! ReadGeoModel is set." << std::endl; + + /* reading data from the imported .db file by usinhg the reader object */ + std::cout << "Reading the same records from the imported geometry DB file..." + << std::endl; + geoReader.printDBTable("Materials"); + geoReader.printDBTable("Elements"); + + + /* build the GeoModel tree and load it in memory */ + const GeoVPhysVol* world = geoReader.buildGeoModel(); + + + // --- Reading the properties of the 'world' volume retrieved from the .db file + std::cout << "Getting the GeoLogVol used by the 'world' volume" + << std::endl; + const GeoLogVol* logVol = world->getLogVol(); + std::cout << "'world' GeoLogVol name: " << logVol->getName() << std::endl; + std::cout << "'world' GeoMaterial name: " + << logVol->getMaterial()->getName() << std::endl; + + // --- Reading the imported Geometry + + // get number of children volumes + unsigned int nChil = world->getNChildVols(); + std::cout << "'world' number of children: " << nChil << std::endl; + + // loop over all children nodes + std::cout << "Looping over all 'volume' children (i.e., GeoPhysVol and " + "GeoFullPhysVol)..." + << std::endl; + for (unsigned int idx = 0; idx < nChil; ++idx) { + PVConstLink nodeLink = world->getChildVol(idx); + + if (dynamic_cast<const GeoVPhysVol*>(&(*(nodeLink)))) { + std::cout << "\t" + << "the child n. " << idx << " "; + const GeoVPhysVol* childVolV = &(*(nodeLink)); + + if (dynamic_cast<const GeoPhysVol*>(childVolV)) { + const GeoPhysVol* childVol = + dynamic_cast<const GeoPhysVol*>(childVolV); + std::cout << "is a GeoPhysVol, whose GeoLogVol name is: " + << childVol->getLogVol()->getName(); + std::cout << " and it has " << childVol->getNChildVols() + << " child volumes" << std::endl; + } else if (dynamic_cast<const GeoFullPhysVol*>(childVolV)) { + const GeoFullPhysVol* childVol = + dynamic_cast<const GeoFullPhysVol*>(childVolV); + std::cout << "is a GeoFullPhysVol, whose GeoLogVol name is: " + << childVol->getLogVol()->getName(); + std::cout << " and it has " << childVol->getNChildVols() + << " child volumes" << std::endl; + } + } else if (dynamic_cast<const GeoNameTag*>(&(*(nodeLink)))) { + std::cout << "\t" + << "the child n. " << idx << " is a GeoNameTag" + << std::endl; + const GeoNameTag* childVol = + dynamic_cast<const GeoNameTag*>(&(*(nodeLink))); + std::cout << "\t\t GeoNameTag's name: " << childVol->getName() + << std::endl; + } else if (dynamic_cast<const GeoMaterial*>(&(*(nodeLink)))) { + std::cout << "\t" + << "the child n. " << idx << " is a GeoMaterial" + << std::endl; + const GeoMaterial* childVol = + dynamic_cast<const GeoMaterial*>(&(*(nodeLink))); + std::cout << "\t\t GeoMaterial's name: " << childVol->getName() + << std::endl; + std::cout << "\t\t GeoMaterial's number of elements: " + << childVol->getNumElements() << std::endl; + } + } + + std::cout << "Everything done." << std::endl; + + // return app.exec(); + return 0; +} diff --git a/GeoModelExamples/HelloGeoRead2G4/CMakeLists.txt b/GeoModelExamples/HelloGeoRead2G4/CMakeLists.txt index be563d9b336cbcf6dbf6fa71e54da44aa1682e9d..db4e5b1ec7a8a6051037de39131b80a2d8b3c4ce 100644 --- a/GeoModelExamples/HelloGeoRead2G4/CMakeLists.txt +++ b/GeoModelExamples/HelloGeoRead2G4/CMakeLists.txt @@ -1,21 +1,25 @@ -# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +# Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration ################################################################################ # Package: HelloGeoRead2G4 # author: Riccardo Maria BIANCHI @ CERN - Nov, 2018 +# update: Riccardo Maria BIANCHI @ CERN - Jul, 2023 ################################################################################ -cmake_minimum_required(VERSION 3.1.0) +cmake_minimum_required(VERSION 3.16...3.26) -#project(HelloGeoRead2G4) +project(HelloGeoRead2G4) # Find includes in current dir set(CMAKE_INCLUDE_CURRENT_DIR ON) # Find the needed dependencies, when building individually if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) + message(STATUS "Compiling the example '${PROJECT_NAME}' as a standalone project...") find_package( GeoModelCore REQUIRED ) find_package( GeoModelIO REQUIRED ) + find_package( GeoModelG4 REQUIRED ) + find_package( Eigen3 REQUIRED ) endif() ## External dependencies. @@ -24,10 +28,10 @@ find_package( Geant4 REQUIRED ) include(${Geant4_USE_FILE}) # Populate a CMake variable with the sources -set( SRCS main.cpp ) +set( SRCS HelloGeoReadG4.cpp ) # Tell CMake to create the helloworld executable add_executable( hellogeoRead2G4 ${SRCS} ) # Link all needed libraries -target_link_libraries( hellogeoRead2G4 GeoModelDBManager GeoModelRead GeoModelKernel GeoModel2G4 ${Geant4_LIBRARIES}) +target_link_libraries( hellogeoRead2G4 GeoModelIO::GeoModelDBManager GeoModelIO::GeoModelRead GeoModelCore::GeoModelKernel GeoModel2G4 Eigen3::Eigen ${Geant4_LIBRARIES}) diff --git a/GeoModelExamples/HelloGeoRead2G4/HelloGeoReadG4.cpp b/GeoModelExamples/HelloGeoRead2G4/HelloGeoReadG4.cpp new file mode 100644 index 0000000000000000000000000000000000000000..41a81541636bd4afaad5c060d87830b12f3d9c02 --- /dev/null +++ b/GeoModelExamples/HelloGeoRead2G4/HelloGeoReadG4.cpp @@ -0,0 +1,173 @@ +// Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration + +/* + * HelloGeoReadG4.cpp + * + * Author: Riccardo Maria BIANCHI @ CERN + * Created on: Nov, 2018 + * + */ + +// GeoModel includes +#include "GeoModel2G4/ExtParameterisedVolumeBuilder.h" +#include "GeoModelDBManager/GMDBManager.h" +#include "GeoModelKernel/GeoBox.h" +#include "GeoModelKernel/GeoFullPhysVol.h" +#include "GeoModelKernel/GeoNameTag.h" +#include "GeoModelKernel/GeoPhysVol.h" +#include "GeoModelRead/ReadGeoModel.h" + +// Geant4 includes +#include "G4LogicalVolume.hh" + +// C++ includes +#include <cstdlib> // EXIT_FAILURE +#include <fstream> +#include <iostream> + +// Units +#include "GeoModelKernel/Units.h" +#define SYSTEM_OF_UNITS \ + GeoModelKernelUnits // so we will get, e.g., 'GeoModelKernelUnits::cm' + +/* +// TODO: int main(int argc, char *argv[]) +int main() { + // Set a valid local geometry db path before first run + static const std::string path = "../geometry.db"; + + std::cout << "Using this DB file:" << path << std::endl; + + // check if DB file exists. If not, return. + // FIXME: TODO: this check should go in the 'GMDBManager' constructor. + std::ifstream infile(path.c_str()); + if (infile.good()) { + std::cout << "\n\tERROR!! A '" << path + << "' file exists already!! Please, remove, move, or rename " + "it before running this program. Exiting..."; + exit(EXIT_FAILURE); + } + infile.close(); +*/ +int main(int argc, char* argv[]) { + if (argc != 2) { + fprintf(stderr, "\nERROR!\nusage: %s <input_database.db>\n\n", argv[0]); + return 1; + } + // Get the input SQLite '.db' file containing the geometry + std::string line; + std::string fileName; + fileName = argv[1]; + std::cout << "Using this SQLite '.db' file:" << fileName << std::endl; + + // check if DB file exists. If not, return. + // FIXME: TODO: this check should go in the 'GMDBManager' constructor. + std::ifstream infile(fileName.c_str()); + if (!infile.good()) { + std::cout << "\n\tERROR!! A '" << fileName + << "' file does not exist!! Please, check the path of the " + "input file before running this program. Exiting..."; + exit(EXIT_FAILURE); + } + infile.close(); + + // open the DB + GMDBManager* db = new GMDBManager(fileName); + + /* Open database */ + if (db->checkIsDBOpen()) { + std::cout << "OK! Database is open!\n"; + } else { + std::cout << "Database is not open!\n"; + exit(EXIT_FAILURE); + } + + // -- testing the input database + std::cout << "\n=== Printing the list of all tables in the input DB:" + << std::endl; + db->printAllDBTables(); + std::cout << "\n=== Printing the list of all GeoMaterial nodes:" + << std::endl; + db->printAllMaterials(); + std::cout << "\n=== Printing the list of all GeoLogVol nodes:" << std::endl; + db->printAllLogVols(); + + /* setup the GeoModel reader */ + GeoModelIO::ReadGeoModel readInGeo = GeoModelIO::ReadGeoModel(db); + std::cout << "ReadGeoModel set.\n"; + + /* build the GeoModel geometry */ + const GeoVPhysVol* world = + readInGeo.buildGeoModel(); // builds the whole GeoModel tree in memory + // and get an handle to the 'world' volume + std::cout << "ReadGeoModel::buildGeoModel() done.\n"; + + // --- testing the imported ATLAS Geometry + + // get the GeoLogVol used for the 'world' volume + std::cout << "Getting the GeoLogVol used by the 'world' volume" + << std::endl; + const GeoLogVol* logVol = world->getLogVol(); + std::cout << "'world' GeoLogVol name: " << logVol->getName() << std::endl; + std::cout << "'world' GeoMaterial name: " + << logVol->getMaterial()->getName() << std::endl; + + // get number of children volumes + unsigned int nChil = world->getNChildVols(); + std::cout << "'world' number of children: " << nChil << std::endl; + + // loop over all children nodes + std::cout << "Looping over all 'volume' children (i.e., GeoPhysVol and " + "GeoFullPhysVol)..." + << std::endl; + for (unsigned int idx = 0; idx < nChil; ++idx) { + PVConstLink nodeLink = world->getChildVol(idx); + + if (dynamic_cast<const GeoVPhysVol*>(&(*(nodeLink)))) { + std::cout << "\t" + << "the child n. " << idx << " "; + const GeoVPhysVol* childVolV = &(*(nodeLink)); + if (dynamic_cast<const GeoPhysVol*>(childVolV)) + + { + const GeoPhysVol* childVol = + dynamic_cast<const GeoPhysVol*>(childVolV); + std::cout << "is a GeoPhysVol, whose GeoLogVol name is: " + << childVol->getLogVol()->getName() << std::endl; + std::cout << " and it has " << childVol->getNChildVols() + << " child volumes\n"; + + } else if (dynamic_cast<const GeoFullPhysVol*>(childVolV)) { + const GeoFullPhysVol* childVol = + dynamic_cast<const GeoFullPhysVol*>(childVolV); + std::cout << "is a GeoFullPhysVol, whose GeoLogVol name is: " + << childVol->getLogVol()->getName() << std::endl; + std::cout << " and it has " << childVol->getNChildVols() + << " child volumes\n"; + } + } else if (dynamic_cast<const GeoNameTag*>(&(*(nodeLink)))) { + std::cout << "\t" + << "the child n. " << idx << " is a GeoNameTag\n"; + const GeoNameTag* childVol = + dynamic_cast<const GeoNameTag*>(&(*(nodeLink))); + std::cout << "\t\tGeoNameTag's name: " << childVol->getName() + << std::endl; + // std::cout<< " and it has "<<childVol->getNChildVols()<<" child + // volumes\n"; + } + } + + // build the Geant4 geometry and get an hanlde to the world' volume + ExtParameterisedVolumeBuilder* builder = + new ExtParameterisedVolumeBuilder("ATLAS"); + std::cout << "Building G4 geometry." << std::endl; + G4LogicalVolume* g4World = builder->Build(world); + + std::cout << "This is the newly-created Geant4 G4LogicalVolume, ready to " + "be used: " + << g4World << std::endl; + + std::cout << "Everything done.\n"; + + return 0; +} diff --git a/GeoModelExamples/HelloGeoRead2G4/README.md b/GeoModelExamples/HelloGeoRead2G4/README.md index a3f5efe0a76b55f75bba8430e61615014edf3682..a3b9b9e9385225d2f50501420aefc5fe2f4dd19e 100644 --- a/GeoModelExamples/HelloGeoRead2G4/README.md +++ b/GeoModelExamples/HelloGeoRead2G4/README.md @@ -7,7 +7,7 @@ This is built on top of the [`hellogeo` example program](https://gitlab.cern.ch/ The example program: - 1. loads the geometry from the `.db` file + 1. loads the geometry specified as input in a `.db` file 2. prints all GeoMaterial entries found in the `.db` 3. builds the GeoModel tree, storing it in memory 4. gets the RootVolume of the GeoModel tree and it prints out the number of its children @@ -15,122 +15,19 @@ The example program: 6. transforms the GeoModel tree to Geant4 geometry -## Dependencies - -### Install Qt5 - -To build and run GeoModel I/O libraries, you must have a working Qt5 installation on your computer. -If you are not sure how to install it, please take a look at the Appendix, below. - - -### CLHEP - -Geant4 needs [CLHEP](https://gitlab.cern.ch/CLHEP). - -We checkout and build the latest release of CLHEP: - -```bash -git clone https://gitlab.cern.ch/CLHEP/CLHEP.git -cd CLHEP -git checkout CLHEP_2_4_1_0 # get the latest release -cd ../ -mkdir CLHEP_build -cd CLHEP_build -cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=RelWithDebInfo ../CLHEP/ -make -j4 -make install -``` - -### Geant4 - -We checkout and build the latest release of Geant4: - -```bash -git clone https://gitlab.cern.ch/geant4/geant4.git -cd geant4 -git checkout v10.5.0 -cd ../ -mkdir build_geant4 -cd build_geant4 -cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=RelWithDebInfo ../geant4/ -make -j 4 -make install -``` - -### Build GeoModel dependencies - -#### Build GeoModelCore - -```bash -git clone --recurse-submodules ssh://git@gitlab.cern.ch:7999/GeoModelDev/GeoModelCore.git -mkdir build_gmk -cd build_gmk -cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=RelWithDebInfo ../GeoModelCore -make -j 4 -make install -``` -#### Build GeoModelIO dependencies - -```bash -git clone --recurse-submodules ssh://git@gitlab.cern.ch:7999/GeoModelDev/GeoModelIO.git -mkdir build_gmk -cd build_gmk -cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=RelWithDebInfo ../GeoModelIO -make -j 4 -make install -``` -#### Build GeoModelG4 dependencies - -```bash -git clone --recurse-submodules ssh://git@gitlab.cern.ch:7999/GeoModelDev/GeoModelG4.git -mkdir build_gmk -cd build_gmk -cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=RelWithDebInfo ../GeoModelG4 -make -j 4 -make install -``` - - ## Build -From your work folder: - -```bash -git clone ssh://git@gitlab.cern.ch:7999/GeoModelDev/GeoModelExamples.git -mkdir build_hellogeoRead2G4 -cd build_hellogeoRead2G4 -cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=RelWithDebInfo ../GeoModelExamples/HelloGeoRead2G4 -make -j4 -make install -``` -**Note:** If you installed Geant4 in a folder other than the `../install`, then you have to pass the path to Geant4 adding the -DGeant4_DIR option to cmake - -```bash -cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=RelWithDebInfo ../GeoModelG4/ -DGeant4_DIR=<path-to-Geant4-install>/lib/Geant4-10.x.y/ -``` +To build the GeoModelExamples please refer to the documentation at [GeoModel website](https://geomodel.web.cern.ch/home/) ## Run `hellogeoRead2G4` Get sample geometry data to play with: ```bash -wget https://atlas-vp1.web.cern.ch/atlas-vp1/doc_new/sample_datafiles/geometry/geometry-ATLAS-R2-2015-03-01-00.db -ln -s $PWD/geometry-ATLAS-R2-2015-03-01-00.db ../geometry.db +wget https://geomodel.web.cern.ch/atlas-geometry-data/geometry-ATLAS-R3S-2021-03-02-00.db ``` - Now, you can run the example by typing: ```bash -./hellogeoRead2G4 +./hellogeoRead2G4 geometry-ATLAS-R3S-2021-03-02-00.db ``` - - - ---- - -## Appendix - -### Notes on Qt5 - -To build and run GeoModel I/O libraries, you must have a working Qt5 installation on your computer. Qt5 classes are used for I/O operations with the underlying SQLite daemon, to store/handle data, and to handle logging. - -If you are not sure how to install it, please take a look at [the notes on Qt5, in the GeoModelIO repository](https://gitlab.cern.ch/GeoModelDev/GeoModelIO/blob/master/README_QT5_NOTES.md). diff --git a/GeoModelExamples/HelloGeoRead2G4/main.cpp b/GeoModelExamples/HelloGeoRead2G4/main.cpp deleted file mode 100644 index 398b5b70977173675ba3c56733c2d6807bf4d441..0000000000000000000000000000000000000000 --- a/GeoModelExamples/HelloGeoRead2G4/main.cpp +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration - -/* - * HelloGeo.cpp - * - * Author: Riccardo Maria BIANCHI @ CERN - * Created on: Nov, 2018 - * - */ - -// GeoModel includes -#include "GeoModel2G4/ExtParameterisedVolumeBuilder.h" -#include "GeoModelDBManager/GMDBManager.h" -#include "GeoModelRead/ReadGeoModel.h" -#include "GeoModelKernel/GeoBox.h" -#include "GeoModelKernel/GeoPhysVol.h" -#include "GeoModelKernel/GeoFullPhysVol.h" -#include "GeoModelKernel/GeoNameTag.h" - -// Geant4 includes -#include "G4LogicalVolume.hh" - -// C++ includes -#include <iostream> -#include <fstream> -#include <cstdlib> // EXIT_FAILURE - - -// Units -#include "GeoModelKernel/Units.h" -#define SYSTEM_OF_UNITS GeoModelKernelUnits // so we will get, e.g., 'GeoModelKernelUnits::cm' - - -// GeoModelExperiment* createTheExperiment(GeoPhysVol* world) -// { -// if (world == nullptr) -// { -// // Setup the 'World' volume from which everything else will be suspended -// double densityOfAir=0.1; -// const GeoMaterial* worldMat = new GeoMaterial("std::Air", densityOfAir); -// const GeoBox* worldBox = new GeoBox(1000*SYSTEM_OF_UNITS::cm, 1000*SYSTEM_OF_UNITS::cm, 1000*SYSTEM_OF_UNITS::cm); -// const GeoLogVol* worldLog = new GeoLogVol("WorldLog", worldBox, worldMat); -// world = new GeoPhysVol(worldLog); -// } -// // Setup the 'Experiment' manager -// GeoModelExperiment* theExperiment = new GeoModelExperiment(world); -// return theExperiment; -// } - - - -// TODO: int main(int argc, char *argv[]) -int main() -{ - - // Set a valid local geometry db path before first run - static const std::string path = "../geometry.db"; - - std::cout << "Using this DB file:" << path << std::endl; - - // check if DB file exists. If not, return. - // FIXME: TODO: this check should go in the 'GMDBManager' constructor. - std::ifstream infile(path.c_str()); - if ( infile.good() ) { - std::cout << "\n\tERROR!! A '" << path << "' file exists already!! Please, remove, move, or rename it before running this program. Exiting..."; - exit(EXIT_FAILURE); - } - infile.close(); - - // open the DB - GMDBManager* db = new GMDBManager(path); - - /* Open database */ - if (db->checkIsDBOpen()) { - std::cout << "OK! Database is open!\n"; - } - else { - std::cout << "Database is not open!\n"; - exit(EXIT_FAILURE); - } - - // -- testing the input database - std::cout << "Printing the list of all GeoMaterial nodes" << std::endl; - db->printAllMaterials(); - - /* setup the GeoModel reader */ - GeoModelIO::ReadGeoModel readInGeo = GeoModelIO::ReadGeoModel(db); - std::cout << "ReadGeoModel set.\n"; - - - /* build the GeoModel geometry */ - GeoPhysVol* world = readInGeo.buildGeoModel(); // builds the whole GeoModel tree in memory and get an handle to the 'world' volume - std::cout << "ReadGeoModel::buildGeoModel() done.\n"; - - - - // --- testing the imported ATLAS Geometry - - // get the GeoLogVol used for the 'world' volume - std::cout << "Getting the GeoLogVol used by the 'world' volume" << std::endl; - const GeoLogVol* logVol = world->getLogVol(); - std::cout << "'world' GeoLogVol name: " << logVol->getName() << std::endl; - std::cout << "'world' GeoMaterial name: " << logVol->getMaterial()->getName() << std::endl; - - // get number of children volumes - unsigned int nChil = world->getNChildVols(); - std:: cout << "'world' number of children: " << nChil << std::endl; - - // loop over all children nodes - std::cout << "Looping over all 'volume' children (i.e., GeoPhysVol and GeoFullPhysVol)..." << std::endl; - for (unsigned int idx=0; idx<nChil; ++idx) { - PVConstLink nodeLink = world->getChildVol(idx); - - if ( dynamic_cast<const GeoVPhysVol*>( &(*( nodeLink ))) ) { - std::cout << "\t" << "the child n. " << idx << " "; - const GeoVPhysVol *childVolV = &(*( nodeLink )); - if ( dynamic_cast<const GeoPhysVol*>(childVolV) ) - - { - const GeoPhysVol* childVol = dynamic_cast<const GeoPhysVol*>(childVolV); - std::cout << "is a GeoPhysVol, whose GeoLogVol name is: " << childVol->getLogVol()->getName() << std::endl; - std::cout<< " and it has "<<childVol->getNChildVols()<<" child volumes\n"; - - } else if ( dynamic_cast<const GeoFullPhysVol*>(childVolV) ) { - const GeoFullPhysVol* childVol = dynamic_cast<const GeoFullPhysVol*>(childVolV); - std::cout << "is a GeoFullPhysVol, whose GeoLogVol name is: " << childVol->getLogVol()->getName() << std::endl; - std::cout<< " and it has "<<childVol->getNChildVols()<<" child volumes\n"; - } - } else if ( dynamic_cast<const GeoNameTag*>( &(*( nodeLink ))) ) { - std::cout << "\t" << "the child n. " << idx << " is a GeoNameTag\n"; - const GeoNameTag *childVol = dynamic_cast<const GeoNameTag*>(&(*( nodeLink ))); - std::cout << "\t\tGeoNameTag's name: " << childVol->getName() << std::endl; - //std::cout<< " and it has "<<childVol->getNChildVols()<<" child volumes\n"; - } - } - - // build the Geant4 geometry and get an hanlde to the world' volume - ExtParameterisedVolumeBuilder* builder = new ExtParameterisedVolumeBuilder("ATLAS"); - std::cout << "Building G4 geometry."<<std::endl; - G4LogicalVolume* g4World = builder->Build(world); - - std::cout << "This is the newly-created Geant4 G4LogicalVolume, ready to be used: " << g4World << std::endl; - - std::cout << "Everything done.\n"; - - return 0; -} diff --git a/GeoModelExamples/HelloGeoReadNodeAction/CMakeLists.txt b/GeoModelExamples/HelloGeoReadNodeAction/CMakeLists.txt index 68ce5cafcd820bc195654e8f1747a7969ed43ee3..3b64ca9add2c9862c2173fd476abff585ef40ae3 100644 --- a/GeoModelExamples/HelloGeoReadNodeAction/CMakeLists.txt +++ b/GeoModelExamples/HelloGeoReadNodeAction/CMakeLists.txt @@ -5,7 +5,7 @@ # author: Riccardo Maria BIANCHI @ CERN - May, 2022 ################################################################################ -cmake_minimum_required(VERSION 3.1.0) +cmake_minimum_required(VERSION 3.16...3.26) #project(HelloGeoRead) diff --git a/GeoModelExamples/HelloGeoReadNodeAction/README.md b/GeoModelExamples/HelloGeoReadNodeAction/README.md index 8bfbbf64e13d6c6c767c9eb9193ec744f5ff8e7e..17df2f1ad0c3dd4352104071e9fe0ea57a0d12ec 100644 --- a/GeoModelExamples/HelloGeoReadNodeAction/README.md +++ b/GeoModelExamples/HelloGeoReadNodeAction/README.md @@ -1,6 +1,6 @@ -# The 'helloGeoRead' GeoModel example +# The 'HelloGeoReadNodeAction' GeoModel example -The `helloGeoRead` example shows you how to read persistified GeoModel data in a standalone program. +The `HelloGeoReadNodeAction` example shows you how to read persistified GeoModel data in a standalone program. The example program: @@ -13,70 +13,21 @@ The example program: The example program uses many of the GeoModel packages. -## Dependencies - -### Install Qt5 - -To build and run GeoModel libraries, you must have a working Qt5 installation on your computer. -If you are not sure how to install it, please take a look at the Appendix on Qt5, below. - -### Build GeoModelCore - -```bash -git clone ssh://git@gitlab.cern.ch:7999/GeoModelDev/GeoModelCore.git -mkdir build_gmcore -cd build_gmcore -cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=RelWithDebInfo ../GeoModelCore -make -j 4 -make install -``` - -### Build GeoModelIO - -```bash -git clone ssh://git@gitlab.cern.ch:7999/GeoModelDev/GeoModelIO.git -mkdir build_gmio -cd build_gmio -cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=RelWithDebInfo ../GeoModelIO -make -j 4 -make install -``` - ## Build -From your work folder: - -```bash -git clone ssh://git@gitlab.cern.ch:7999/GeoModelDev/GeoModelExamples.git -mkdir build_hellogeoRead -cd build_hellogeoRead -cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=RelWithDebInfo ../GeoModelExamples/HelloGeoRead -make -j4 -make install -``` +To build the GeoModelExamples please refer to the documentation at [GeoModel website](https://geomodel.web.cern.ch/home/) ## Run Get sample geometry data to play with: ```bash -wget https://atlas-vp1.web.cern.ch/atlas-vp1/doc_new/sample_datafiles/geometry/geometry-ATLAS-R2-2015-03-01-00.db -ln -s $PWD/geometry-ATLAS-R2-2015-03-01-00.db ../geometry.db +wget https://geomodel.web.cern.ch/atlas-geometry-data/geometry-ATLAS-R3S-2021-03-02-00.db +ln -s $PWD/geometry-ATLAS-R3S-2021-03-02-00.db ../geometry.db ``` Now, you can run the example by typing: ```bash -./hellogeoRead +./hellogeoReadNodeAction geometry.db ``` - - - ---- - -## Appendix - -### Notes on Qt5 - -To build and run GeoModel I/O libraries, you must have a working Qt5 installation on your computer. Qt5 classes are used for I/O operations with the underlying SQLite daemon, to store/handle data, and to handle logging. - -If you are not sure how to install it, please take a look at [the notes on Qt5, in the GeoModelIO repository](https://gitlab.cern.ch/GeoModelDev/GeoModelIO/blob/master/README_QT5_NOTES.md). diff --git a/GeoModelExamples/HelloGeoReadNodeAction/main.cxx b/GeoModelExamples/HelloGeoReadNodeAction/main.cxx index 0107074b3c99c1ba1307d02b45a43cc8d141a0db..ac52eb469f63ade02921198467a19dc0d27a77b1 100644 --- a/GeoModelExamples/HelloGeoReadNodeAction/main.cxx +++ b/GeoModelExamples/HelloGeoReadNodeAction/main.cxx @@ -1,7 +1,7 @@ -// Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration +// Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration /* - * HelloGeo.cpp + * HelloGeoReadNodeAction.cpp * * Author: Riccardo Maria BIANCHI @ CERN * Created on: May, 2022 @@ -30,11 +30,9 @@ #define SYSTEM_OF_UNITS GeoModelKernelUnits // so we will get, e.g., 'GeoModelKernelUnits::cm' -GeoPhysVol* createTheWorld(GeoPhysVol* world) +GeoVPhysVol* createTheWorld() { - if (world == nullptr) - { - //-----------------------------------------------------------------------------------// + //-----------------------------------------------------------------------------------// // Define the materials that we shall use. // // ----------------------------------------------------------------------------------// @@ -58,11 +56,9 @@ GeoPhysVol* createTheWorld(GeoPhysVol* world) air->add(Hydrogen, 0.0008); air->lock(); - const GeoBox* worldBox = new GeoBox(1000*SYSTEM_OF_UNITS::cm, 1000*SYSTEM_OF_UNITS::cm, 1000*SYSTEM_OF_UNITS::cm); - const GeoLogVol* worldLog = new GeoLogVol("WorldLog", worldBox, air); - world = new GeoPhysVol(worldLog); - } - return world; + const GeoBox* worldBox = new GeoBox(1000*SYSTEM_OF_UNITS::cm, 1000*SYSTEM_OF_UNITS::cm, 1000*SYSTEM_OF_UNITS::cm); + const GeoLogVol* worldLog = new GeoLogVol("WorldLog", worldBox, air); + return new GeoPhysVol(worldLog); } @@ -72,7 +68,7 @@ int main(int argc, char *argv[]) if(argc != 2) { - fprintf(stderr, "\nERROR!\nusage: %s input.db\n\n", argv[0]); + fprintf(stderr, "\nERROR!\nUsage: %s geometry.db\n\n", argv[0]); return 1; } // Get the input SQLite '.db' file containing the geometry @@ -120,7 +116,7 @@ int main(int argc, char *argv[]) /* build the GeoModel geometry */ - GeoPhysVol* dbPhys = geoReader.buildGeoModel(); // builds the whole GeoModel tree in memory + const GeoVPhysVol* dbPhys = geoReader.buildGeoModel(); // builds the whole GeoModel tree in memory std::cout << "ReadGeoModel::buildGeoModel() done." << std::endl; std::cout << "Reading records from the imported geometry DB file..." << std::endl; @@ -131,7 +127,7 @@ int main(int argc, char *argv[]) // create the world volume container and // get the 'world' volume, i.e. the root volume of the GeoModel tree std::cout << "Getting the 'world' GeoPhysVol, i.e. the root volume of the GeoModel tree" << std::endl; - GeoPhysVol* world = createTheWorld(dbPhys); + const GeoVPhysVol* world = dbPhys ? dbPhys : createTheWorld(); std::cout << "Getting the GeoLogVol used by the 'world' volume" << std::endl; const GeoLogVol* logVol = world->getLogVol(); std::cout << "'world' GeoLogVol name: " << logVol->getName() << std::endl; diff --git a/GeoModelExamples/HelloGeoWrite/CMakeLists.txt b/GeoModelExamples/HelloGeoWrite/CMakeLists.txt index 498d3b3f24b9b2a55438a772f0778a323bc63dfb..653d49852205a94d6e64793adb84baedc396d3e4 100644 --- a/GeoModelExamples/HelloGeoWrite/CMakeLists.txt +++ b/GeoModelExamples/HelloGeoWrite/CMakeLists.txt @@ -5,9 +5,9 @@ # author: Riccardo Maria BIANCHI @ CERN - Nov, 2018 ################################################################################ -cmake_minimum_required(VERSION 3.1.0) +cmake_minimum_required(VERSION 3.16...3.26) -#project(HelloGeoWrite) +project(HelloGeoWrite) # Compile with C++17 set(CMAKE_CXX_STANDARD 17) @@ -29,4 +29,4 @@ set(SRCS main.cpp ) add_executable( hellogeoWrite ${SRCS} ) # Link all needed libraries -target_link_libraries( hellogeoWrite GeoModelCore::GeoModelKernel GeoModelIO::GeoModelWrite ) +target_link_libraries( hellogeoWrite GeoModelCore::GeoModelKernel GeoModelIO::GeoModelWrite GeoModelIO::GeoModelIOHelpers) diff --git a/GeoModelExamples/HelloGeoWrite/README.md b/GeoModelExamples/HelloGeoWrite/README.md index f9d98f364d3ae07f54458cb6e3312559e0467d33..5ca9af3d58b23b38f41ccd3601321f9a2e6476e4 100644 --- a/GeoModelExamples/HelloGeoWrite/README.md +++ b/GeoModelExamples/HelloGeoWrite/README.md @@ -8,51 +8,10 @@ The example program: 2. Writes the geometry to an SQLite file 3. It accesses the persistent copy of the geometry, as a test - -## Dependencies - -### Install Qt5 - -To build and run GeoModel I/O libraries, you must have a working Qt5 installation on your computer. -If you are not sure how to install it, please take a look at the Appendix, below. - - -#### GeoModelCore - -```bash -git clone ssh://git@gitlab.cern.ch:7999/GeoModelDev/GeoModelCore.git -mkdir build_gmcore -cd build_gmcore -cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=RelWithDebInfo ../GeoModelCore -make -j 4 -make install -cd .. -``` - -#### GeoModelIO - -```bash -git clone ssh://git@gitlab.cern.ch:7999/GeoModelDev/GeoModelIO.git -mkdir build_gmio -cd build_gmio -cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=RelWithDebInfo ../GeoModelIO -make -j 4 -make install -``` - - - ## Build -From your work folder: +To build the GeoModelExamples please refer to the documentation at [GeoModel website](https://geomodel.web.cern.ch/home/) -```bash -git clone ssh://git@gitlab.cern.ch:7999/GeoModelDev/GeoModelExamples.git -mkdir build_hellogeo -cd build_hellogeo -cmake -DCMAKE_INSTALL_PREFIX=../install ../GeoModelExamples/HelloGeoWrite/ -make -j4 -``` ## Run @@ -61,14 +20,3 @@ Now, you can **run the example** by typing: ```bash ./hellogeoWrite ``` - - ----- - -## Appendix - -### Notes on Qt5 - -To build and run GeoModel I/O libraries, you must have a working Qt5 installation on your computer. Qt5 classes are used for I/O operations with the underlying SQLite daemon, to store/handle data, and to handle logging. - -If you are not sure how to install it, please take a look at [the notes on Qt5, in the GeoModelIO repository](https://gitlab.cern.ch/GeoModelDev/GeoModelIO/blob/master/README_QT5_NOTES.md). diff --git a/GeoModelExamples/HelloGeoWrite/main.cpp b/GeoModelExamples/HelloGeoWrite/main.cpp index b35d09f64ddf677b355768c12cc6fd3db5cb959c..1838ad03d9635dbb37ea48be75eb5e06aef89a16 100644 --- a/GeoModelExamples/HelloGeoWrite/main.cpp +++ b/GeoModelExamples/HelloGeoWrite/main.cpp @@ -1,10 +1,11 @@ -// Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +// Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration /* - * HelloGeo.cpp + * HelloGeoWrite.cpp * * Author: Riccardo Maria BIANCHI @ CERN * Created on: Apr, 2019 + * Updated on: Nov, 2023 - Riccardo Maria BIANCHI - moved to I/O helpers * */ @@ -13,22 +14,80 @@ #include "GeoModelKernel/GeoPhysVol.h" #include "GeoModelKernel/GeoFullPhysVol.h" #include "GeoModelKernel/GeoNameTag.h" -#include "GeoModelDBManager/GMDBManager.h" -#include "GeoModelWrite/WriteGeoModel.h" +#include "GeoModelIOHelpers/GMIO.h" // C++ includes #include <iostream> #include <fstream> #include <cstdlib> // EXIT_FAILURE +#include <getopt.h> // runtime options // Units #include "GeoModelKernel/Units.h" #define SYSTEM_OF_UNITS GeoModelKernelUnits // so we will get, e.g., 'GeoModelKernelUnits::cm' +/* print a description of all supported options */ +void usage (FILE *fp, const char *path) +{ + /* take only the last portion of the path */ + const char *basename = strrchr(path, '/'); + basename = basename ? basename + 1 : path; + + fprintf (fp, "usage: %s [OPTION]\n", basename); + fprintf (fp, " -h, --help\t\t" + "Print this help and exit.\n"); + fprintf (fp, " -d, --forceDelete\t" + "Force the deletion of an existing output file with the same name (i.e., Replace the existing output file).\n"); +} + + + int main(int argc, char *argv[]) { + // warning message to teh user + std::cout << "\n*** NOTE ***\n" + << "Please, notice: you should use the 'forceDelete' option\n" + << "if you want to overwrite the existing output file." + << "\nRun with the '-h' otion to see the flag.\n***\n\n"; + + // === Command-Line OPTIONS === + int flag_help = 0; + bool flag_forceDelete = false; + option longopts[] = { + { "help", no_argument, &flag_help, 1 }, + {"forceDelete", no_argument, NULL, 'd'}, + {0} + }; + while (1) { + // declare options 'h' and 'd', both without arguments + const int opt = getopt_long(argc, argv, "hd", longopts, 0); + if (opt == -1) { + /* a return value of -1 indicates that there are no more options */ + break; + } + switch (opt) { + case 'h': + flag_help = 1; + break; + case 'd': + flag_forceDelete = true; + break; + case '?': + usage (stderr, argv[0]); + return 1; + default: + break; + } + } + if (flag_help) { + usage (stdout, argv[0]); + return 0; + } + //==================================== + + //-----------------------------------------------------------------------------------// // Define the materials that we shall use. // // ----------------------------------------------------------------------------------// @@ -99,49 +158,24 @@ int main(int argc, char *argv[]) //------------------------------------------------------------------------------------// // Now insert all of this into the world... // GeoNameTag *tag = new GeoNameTag("Toy"); - world->add(tag); + world->add(tag); world->add(toyPhys); //------------------------------------------------------------------------------------// + //------------------------------------------------------------------------------------// + // Writing the geometry to file + //------------------------------------------------------------------------------------// + std::string path = "geometry.db"; + std::cout << "Dumping the GeoModel geometry to the DB file..." << std::endl; + GMDBManager db = GeoModelIO::IO::saveToDB(world, path, 0, flag_forceDelete); + std::cout << "DONE. Geometry saved." <<std::endl; - //------------------------------------------------------------------------------------// - // Writing the geometry to file - //------------------------------------------------------------------------------------// - std::string path = "geometry.db"; - - // check if DB file exists. If not, return. - // FIXME: TODO: this check should go in the 'GMDBManager' constructor. - std::ifstream infile(path.c_str()); - if ( infile.good() ) { - std::cout << "\n\tERROR!! A '" << path << "' file exists already!! Please, remove, move, or rename it before running this program. Exiting..."; - exit(EXIT_FAILURE); - } - infile.close(); - - // open the DB connection - GMDBManager db(path); - - // check the DB connection - if (db.checkIsDBOpen()) { - std::cout << "OK! Database is open!" << std::endl; - } else { - std::cout << "Database ERROR!! Exiting..." << std::endl; - exit(EXIT_FAILURE); - } - - // Dump the tree volumes to a local file - std::cout << "Dumping the GeoModel geometry to the DB file..." << std::endl; - GeoModelIO::WriteGeoModel dumpGeoModelGraph(db); // init the GeoModel node action - world->exec(&dumpGeoModelGraph); // visit all GeoModel nodes - dumpGeoModelGraph.saveToDB(); // save to the SQlite DB file - std::cout << "DONE. Geometry saved." <<std::endl; - - std::cout << "\nTest - list of all the GeoMaterial nodes in the persistified geometry:" << std::endl; - db.printAllMaterials(); - std::cout << "\nTest - list of all the GeoElement nodes in the persistified geometry:" << std::endl; - db.printAllElements(); + std::cout << "\nTest - list of all the GeoMaterial nodes in the persistified geometry:" << std::endl; + db.printAllMaterials(); + std::cout << "\nTest - list of all the GeoElement nodes in the persistified geometry:" << std::endl; + db.printAllElements(); return 0; diff --git a/GeoModelExamples/HelloGeoWriteReadWrite/CMakeLists.txt b/GeoModelExamples/HelloGeoWriteReadWrite/CMakeLists.txt index c10f7fc3e210175d4862acbbab7818af720fa268..b89dcacde94f615fbb7cd04495f8f3b6d6038d94 100644 --- a/GeoModelExamples/HelloGeoWriteReadWrite/CMakeLists.txt +++ b/GeoModelExamples/HelloGeoWriteReadWrite/CMakeLists.txt @@ -5,7 +5,7 @@ # author: Riccardo Maria BIANCHI @ CERN - May, 2022 ################################################################################ -cmake_minimum_required(VERSION 3.1.0) +cmake_minimum_required(VERSION 3.16...3.26) #project(HelloGeoWrite) diff --git a/GeoModelExamples/HelloGeoWriteReadWrite/README.md b/GeoModelExamples/HelloGeoWriteReadWrite/README.md index f9d98f364d3ae07f54458cb6e3312559e0467d33..b1498811d54cf056e9e5fc0b51251c5c7eb72d6c 100644 --- a/GeoModelExamples/HelloGeoWriteReadWrite/README.md +++ b/GeoModelExamples/HelloGeoWriteReadWrite/README.md @@ -1,74 +1,23 @@ -# The 'helloGeoWrite' GeoModel example +# The 'helloGeoWriteReadWrite' GeoModel example -The `helloGeoWrite` example shows you how to create a simple geometry, by using GeoModel nodes. +The `helloGeoWriteReadWrite` example shows you how to create a simple geometry, by using GeoModel nodes. The example program: 1. Builds an example geometry: 2. Writes the geometry to an SQLite file 3. It accesses the persistent copy of the geometry, as a test - - -## Dependencies - -### Install Qt5 - -To build and run GeoModel I/O libraries, you must have a working Qt5 installation on your computer. -If you are not sure how to install it, please take a look at the Appendix, below. - - -#### GeoModelCore - -```bash -git clone ssh://git@gitlab.cern.ch:7999/GeoModelDev/GeoModelCore.git -mkdir build_gmcore -cd build_gmcore -cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=RelWithDebInfo ../GeoModelCore -make -j 4 -make install -cd .. -``` - -#### GeoModelIO - -```bash -git clone ssh://git@gitlab.cern.ch:7999/GeoModelDev/GeoModelIO.git -mkdir build_gmio -cd build_gmio -cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=RelWithDebInfo ../GeoModelIO -make -j 4 -make install -``` - - + 4. Reads it back + 5. Stores it in a new sqlite file ## Build -From your work folder: - -```bash -git clone ssh://git@gitlab.cern.ch:7999/GeoModelDev/GeoModelExamples.git -mkdir build_hellogeo -cd build_hellogeo -cmake -DCMAKE_INSTALL_PREFIX=../install ../GeoModelExamples/HelloGeoWrite/ -make -j4 -``` +To build the GeoModelExamples please refer to the documentation at [GeoModel website](https://geomodel.web.cern.ch/home/) ## Run Now, you can **run the example** by typing: ```bash -./hellogeoWrite +./hellogeoWriteReadWrite ``` - - ----- - -## Appendix - -### Notes on Qt5 - -To build and run GeoModel I/O libraries, you must have a working Qt5 installation on your computer. Qt5 classes are used for I/O operations with the underlying SQLite daemon, to store/handle data, and to handle logging. - -If you are not sure how to install it, please take a look at [the notes on Qt5, in the GeoModelIO repository](https://gitlab.cern.ch/GeoModelDev/GeoModelIO/blob/master/README_QT5_NOTES.md). diff --git a/GeoModelExamples/HelloGeoWriteReadWrite/main.cpp b/GeoModelExamples/HelloGeoWriteReadWrite/main.cpp index 8e2051a5fb1cf9a4473aa365a94f99238607bfa4..a2c2053c8fb166990f6925aba4c90117bf76b059 100644 --- a/GeoModelExamples/HelloGeoWriteReadWrite/main.cpp +++ b/GeoModelExamples/HelloGeoWriteReadWrite/main.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration +// Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration /* * This example writes a sample geometry, reads it back in, then writes it again. @@ -191,7 +191,7 @@ int main(int argc, char *argv[]) GeoModelIO::ReadGeoModel geoReader = GeoModelIO::ReadGeoModel(db2); std::cout << "OK! ReadGeoModel is set." << std::endl; /* build the GeoModel geometry */ - GeoPhysVol* dbPhys = geoReader.buildGeoModel(); // builds the whole GeoModel tree in memory + const GeoVPhysVol* dbPhys = geoReader.buildGeoModel(); // builds the whole GeoModel tree in memory std::cout << "ReadGeoModel::buildGeoModel() done." << std::endl; diff --git a/GeoModelExamples/HelloGeoWrite_direct_noHelpers/CMakeLists.txt b/GeoModelExamples/HelloGeoWrite_direct_noHelpers/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..9efb1aea4486858bb4c1c4cba4014accc823f7e9 --- /dev/null +++ b/GeoModelExamples/HelloGeoWrite_direct_noHelpers/CMakeLists.txt @@ -0,0 +1,32 @@ +# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration + +################################################################################ +# Package: HelloGeoWrite +# author: Riccardo Maria BIANCHI @ CERN - Nov, 2018 +################################################################################ + +cmake_minimum_required(VERSION 3.16...3.26) + +#project(HelloGeoWrite) + +# Compile with C++17 +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS ON) + +if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) # when building individually + find_package( GeoModelCore REQUIRED ) + find_package( GeoModelIO REQUIRED ) +endif() + +# Find includes in current dir +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +# Populate a CMake variable with the sources +set(SRCS main.cpp ) + +# Tell CMake to create the helloworld executable +add_executable( hellogeoWrite ${SRCS} ) + +# Link all needed libraries +target_link_libraries( hellogeoWrite GeoModelCore::GeoModelKernel GeoModelIO::GeoModelWrite ) diff --git a/GeoModelExamples/HelloGeoWrite_direct_noHelpers/README.md b/GeoModelExamples/HelloGeoWrite_direct_noHelpers/README.md new file mode 100644 index 0000000000000000000000000000000000000000..5ca9af3d58b23b38f41ccd3601321f9a2e6476e4 --- /dev/null +++ b/GeoModelExamples/HelloGeoWrite_direct_noHelpers/README.md @@ -0,0 +1,22 @@ +# The 'helloGeoWrite' GeoModel example + +The `helloGeoWrite` example shows you how to create a simple geometry, by using GeoModel nodes. + +The example program: + + 1. Builds an example geometry: + 2. Writes the geometry to an SQLite file + 3. It accesses the persistent copy of the geometry, as a test + +## Build + +To build the GeoModelExamples please refer to the documentation at [GeoModel website](https://geomodel.web.cern.ch/home/) + + +## Run + +Now, you can **run the example** by typing: + +```bash +./hellogeoWrite +``` diff --git a/GeoModelExamples/HelloGeoWrite_direct_noHelpers/main.cpp b/GeoModelExamples/HelloGeoWrite_direct_noHelpers/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7dec1b4d5779b4e1bfdeda690c91c3607b377459 --- /dev/null +++ b/GeoModelExamples/HelloGeoWrite_direct_noHelpers/main.cpp @@ -0,0 +1,159 @@ +// Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration + +/* + * HelloGeoWrite.cpp + * + * This example shows how to build a basic GeoModel tree and write it + * to an SQLite '.db' file without the use of the I/O helper functions. + * That is useful if you want to get a handle on the GeoReader + * object and interact with it directly. + * + * For an example on how to do the same with the use of the convenient I/O helpers, + * take a look at the 'HelloGeoWrite' example instead. + * + * + * Author: Riccardo Maria BIANCHI @ CERN + * Created on: Apr, 2019 + * + * Updated on: Nov, 2023 Riccardo Maria BIANCHI + * + */ + +// GeoModel includes +#include "GeoModelKernel/GeoBox.h" +#include "GeoModelKernel/GeoPhysVol.h" +#include "GeoModelKernel/GeoFullPhysVol.h" +#include "GeoModelKernel/GeoNameTag.h" +#include "GeoModelDBManager/GMDBManager.h" +#include "GeoModelWrite/WriteGeoModel.h" + +// C++ includes +#include <iostream> +#include <fstream> +#include <cstdlib> // EXIT_FAILURE + + +// Units +#include "GeoModelKernel/Units.h" +#define SYSTEM_OF_UNITS GeoModelKernelUnits // so we will get, e.g., 'GeoModelKernelUnits::cm' + + +int main(int argc, char *argv[]) +{ + //-----------------------------------------------------------------------------------// + // Define the materials that we shall use. // + // ----------------------------------------------------------------------------------// + + // Define the units + #define gr SYSTEM_OF_UNITS::gram + #define mole SYSTEM_OF_UNITS::mole + #define cm3 SYSTEM_OF_UNITS::cm3 + + // Define the chemical elements + GeoElement* Nitrogen = new GeoElement ("Nitrogen" ,"N" , 7.0 , 14.0067 *gr/mole); + GeoElement* Oxygen = new GeoElement ("Oxygen" ,"O" , 8.0 , 15.9995 *gr/mole); + GeoElement* Argon = new GeoElement ("Argon" ,"Ar" , 18.0 , 39.948 *gr/mole); + GeoElement* Hydrogen = new GeoElement ("Hydrogen" ,"H" , 1.0 , 1.00797 *gr/mole); + GeoElement* Iron = new GeoElement ("Iron" ,"Fe" , 26.0 , 55.847 *gr/mole); + GeoElement* Carbon = new GeoElement ("Carbon" ,"C" , 6.0 , 12.0107 *gr/mole); + GeoElement* Sillicon = new GeoElement ("Silicon" ,"Si" , 14.0 , 28.085 *gr/mole); + + // Define the materials + + double densityOfAir=0.001214 *gr/cm3; + GeoMaterial *air = new GeoMaterial("Air", densityOfAir); + air->add(Nitrogen , 0.7494); + air->add(Oxygen, 0.2369); + air->add(Argon, 0.0129); + air->add(Hydrogen, 0.0008); + air->lock(); + + GeoMaterial* steel = new GeoMaterial("Steel", 7.9 *gr/cm3); + steel->add(Iron , 0.98); + steel->add(Carbon, 0.02); + steel->lock(); + + // Silicon 100% (Detector) + GeoMaterial* silicon = new GeoMaterial("Silicon", 2.329 *gr/cm3); + silicon->add(const_cast<GeoElement*> (Sillicon), 1.0); + silicon->lock(); + + + //-----------------------------------------------------------------------------------// + // create the world volume container and + // get the 'world' volume, i.e. the root volume of the GeoModel tree + std::cout << "Creating the 'world' volume, i.e. the root volume of the GeoModel tree..." << std::endl; + const GeoBox* worldBox = new GeoBox(1000*SYSTEM_OF_UNITS::cm, 1000*SYSTEM_OF_UNITS::cm, 1000*SYSTEM_OF_UNITS::cm); + const GeoLogVol* worldLog = new GeoLogVol("WorldLog", worldBox, air); + GeoPhysVol* world = new GeoPhysVol(worldLog); + + + //-----------------------------------------------------------------------------------// + // Next make the box that describes the shape of the toy volume: // + const GeoBox *toyBox = new GeoBox(800*SYSTEM_OF_UNITS::cm, 800*SYSTEM_OF_UNITS::cm, 1000*SYSTEM_OF_UNITS::cm); // + // Bundle this with a material into a logical volume: // + const GeoLogVol *toyLog = new GeoLogVol("ToyLog", toyBox, silicon); // + // ..And create a physical volume: // + GeoPhysVol *toyPhys = new GeoPhysVol(toyLog); // + + GeoBox *sPass = new GeoBox(5.0*SYSTEM_OF_UNITS::cm, 30*SYSTEM_OF_UNITS::cm, 30*SYSTEM_OF_UNITS::cm); + GeoLogVol *lPass = new GeoLogVol("Passive", sPass, steel); + GeoPhysVol *pPass = new GeoPhysVol(lPass); + + GeoBox *sIPass = new GeoBox(4*SYSTEM_OF_UNITS::cm, 25*SYSTEM_OF_UNITS::cm, 25*SYSTEM_OF_UNITS::cm); + GeoLogVol *lIPass = new GeoLogVol("InnerPassive", sIPass, air); + GeoPhysVol *pIPass = new GeoPhysVol(lIPass); + + pPass->add(pIPass); + toyPhys->add(pPass); + + //------------------------------------------------------------------------------------// + // Now insert all of this into the world... // + GeoNameTag *tag = new GeoNameTag("Toy"); + world->add(tag); + world->add(toyPhys); + //------------------------------------------------------------------------------------// + + + + + //------------------------------------------------------------------------------------// + // Writing the geometry to file + //------------------------------------------------------------------------------------// + std::string path = "geometry.db"; + + // check if DB file exists. If not, return. + // FIXME: TODO: this check should go in the 'GMDBManager' constructor. + std::ifstream infile(path.c_str()); + if ( infile.good() ) { + std::cout << "\n\tERROR!! A '" << path << "' file exists already!! Please, remove, move, or rename it before running this program. Exiting..."; + exit(EXIT_FAILURE); + } + infile.close(); + + // open the DB connection + GMDBManager db(path); + + // check the DB connection + if (db.checkIsDBOpen()) { + std::cout << "OK! Database is open!" << std::endl; + } else { + std::cout << "Database ERROR!! Exiting..." << std::endl; + exit(EXIT_FAILURE); + } + + // Dump the tree volumes to a local file + std::cout << "Dumping the GeoModel geometry to the DB file..." << std::endl; + GeoModelIO::WriteGeoModel dumpGeoModelGraph(db); // init the GeoModel node action + world->exec(&dumpGeoModelGraph); // visit all GeoModel nodes + dumpGeoModelGraph.saveToDB(); // save to the SQlite DB file + std::cout << "DONE. Geometry saved." <<std::endl; + + std::cout << "\nTest - list of all the GeoMaterial nodes in the persistified geometry:" << std::endl; + db.printAllMaterials(); + std::cout << "\nTest - list of all the GeoElement nodes in the persistified geometry:" << std::endl; + db.printAllElements(); + + + return 0; +} diff --git a/GeoModelExamples/HelloToy/CMakeLists.txt b/GeoModelExamples/HelloToy/CMakeLists.txt index aff08b4673a1b7f88ed8ad8b26abf41d983f763b..0d66f644f671b330132e5d3eacbcae9fc6168211 100644 --- a/GeoModelExamples/HelloToy/CMakeLists.txt +++ b/GeoModelExamples/HelloToy/CMakeLists.txt @@ -5,7 +5,7 @@ # author: Riccardo Maria BIANCHI @ CERN - Aug, 2020 ################################################################################ -cmake_minimum_required(VERSION 3.1.0) +cmake_minimum_required(VERSION 3.16...3.26) #project(HelloToy) diff --git a/GeoModelExamples/HelloToy/step2_read_geo_and_published_nodes.cpp b/GeoModelExamples/HelloToy/step2_read_geo_and_published_nodes.cpp index 1928632cdafc88b5efd24704fe51df3567244a06..28a9df0054a2d4c09fb7557d9582ac443ff3ad3e 100644 --- a/GeoModelExamples/HelloToy/step2_read_geo_and_published_nodes.cpp +++ b/GeoModelExamples/HelloToy/step2_read_geo_and_published_nodes.cpp @@ -150,6 +150,18 @@ int main(int argc, char *argv[]) std::map<unsigned int, GeoFullPhysVol*> mapFPV = readInGeo.getPublishedNodes<unsigned int, GeoFullPhysVol*>("HelloToyExample"); std::map<std::string, GeoAlignableTransform*> mapAXF = readInGeo.getPublishedNodes<std::string, GeoAlignableTransform*>("HelloToyExample"); + //check for a table we know doesn't exist + if (db->checkTable("PublishedFullPhysVols_HelloToyExample")) std::cout<<"We find the table that we expected - good!"<<std::endl; + else std::cout<<"Uh oh, we don't find the expected table - bad!"<<std::endl; + if(!db->checkTable("PublishedFullPhysVols_ByeByeToyExample")) std::cout<<"We don't find the table that we didn't expect - good!"<<std::endl; + else std::cout<<"Uh oh, we found a table which doesn't exist - bad!"<<std::endl; + + //Now test via the specific accessors with additional checks + std::map<unsigned int, GeoFullPhysVol*> mapFPV_test = readInGeo.getPublishedNodes<unsigned int, GeoFullPhysVol*>("ByeByeToyExample",true); + std::map<std::string, GeoAlignableTransform*> mapAXF_test = readInGeo.getPublishedNodes<std::string, GeoAlignableTransform*>("ByeByeToyExample",true); + if(mapFPV_test.size()==0) std::cout<<"Returned an empty FPV map when using checks for a non-existing table - good!"<<std::endl; + if(mapAXF_test.size()==0) std::cout<<"Returned an empty AXF map when using checks for a non-existing table - good!"<<std::endl; + unsigned int ii=0; std::cout << "\n\nPublished AlignableTransforms from the DB...\n"; std::cout << "['xf' is the output of 'getTransform()']\n"; diff --git a/GeoModelExamples/HelloToyDetectorFactory/CMakeLists.txt b/GeoModelExamples/HelloToyDetectorFactory/CMakeLists.txt index 2d4aa975f779baddede0aa9b8659daf7bb3bf9c0..1abe80edad78c1876028499c6a19993cccde2084 100644 --- a/GeoModelExamples/HelloToyDetectorFactory/CMakeLists.txt +++ b/GeoModelExamples/HelloToyDetectorFactory/CMakeLists.txt @@ -5,7 +5,7 @@ # author: Riccardo Maria BIANCHI @ CERN - Nov, 2018 ################################################################################ -cmake_minimum_required(VERSION 3.1.0) +cmake_minimum_required(VERSION 3.16...3.26) #project(HelloToyDetectorFactory) diff --git a/GeoModelExamples/HelloToyDetectorFactory/README.md b/GeoModelExamples/HelloToyDetectorFactory/README.md index 9df3abead5c6f6765602032b12f1cf276a1a84ad..0569f26e409ca2c4c04f95f7e3e4f69b8f066c01 100644 --- a/GeoModelExamples/HelloToyDetectorFactory/README.md +++ b/GeoModelExamples/HelloToyDetectorFactory/README.md @@ -65,4 +65,4 @@ You can visualize it by opening it with VP1Light. Please refer to the [Visualiza To build and run GeoModel I/O libraries, you must have a working Qt5 installation on your computer. Qt5 classes are used for I/O operations with the underlying SQLite daemon, to store/handle data, and to handle logging. -If you are not sure how to install it, please take a look at [the notes on Qt5, in the GeoModelIO repository](https://gitlab.cern.ch/GeoModelDev/GeoModelIO/blob/master/README_QT5_NOTES.md). +If you are not sure how to install it, please take a look at [the notes on Qt5, in the GeoModelIO repository](https://gitlab.cern.ch/GeoModelDev/GeoModelIO/blob/main/README_QT5_NOTES.md). diff --git a/GeoModelExamples/HelloToyDetectorFactory/docs/visualization.md b/GeoModelExamples/HelloToyDetectorFactory/docs/visualization.md index 9df574fee4781c89be2ff3928fb6cbcba4f62650..2cf7f31429330f8cbcb4e7ae629eca12d39d4328 100644 --- a/GeoModelExamples/HelloToyDetectorFactory/docs/visualization.md +++ b/GeoModelExamples/HelloToyDetectorFactory/docs/visualization.md @@ -1,3 +1,5 @@ +# TODO: TO BE UPDATED!! + # Visualizing the 'HelloToyDetectorFactory' geometry with VP1Light  diff --git a/GeoModelExamples/HelloToyXML/CMakeLists.txt b/GeoModelExamples/HelloToyXML/CMakeLists.txt index 2bad58897e17f294d5f064c4d251f27d84499e69..d05f912488d719e4b27ffa905fc25069af11a970 100644 --- a/GeoModelExamples/HelloToyXML/CMakeLists.txt +++ b/GeoModelExamples/HelloToyXML/CMakeLists.txt @@ -5,7 +5,7 @@ # author: Riccardo Maria BIANCHI @ CERN - Aug, 2020 ################################################################################ -cmake_minimum_required(VERSION 3.1.0) +cmake_minimum_required(VERSION 3.16...3.26) project(HelloToyXML) diff --git a/GeoModelExamples/KitchenSinkPlugin/CMakeLists.txt b/GeoModelExamples/KitchenSinkPlugin/CMakeLists.txt index b7f302a25299f2c44af480b4dbef6e83f5b08a8c..03fe5807050a679bbf6f2a76b9640ca601a43a27 100644 --- a/GeoModelExamples/KitchenSinkPlugin/CMakeLists.txt +++ b/GeoModelExamples/KitchenSinkPlugin/CMakeLists.txt @@ -5,7 +5,7 @@ # author: Riccardo Maria BIANCHI @ CERN - Nov, 2018 ################################################################################ -cmake_minimum_required(VERSION 3.1.0) +cmake_minimum_required(VERSION 3.16...3.26) # Compile with C++17 set(CMAKE_CXX_STANDARD 17) diff --git a/GeoModelExamples/KitchenSinkPlugin/src/KitchenSinkPlugin.cxx b/GeoModelExamples/KitchenSinkPlugin/src/KitchenSinkPlugin.cxx index c7cb428b1dc2aa26d531cebd6b79d70c2590f8fe..d1597e8ef72fb6e55c4d7d355bf637d185025ea7 100644 --- a/GeoModelExamples/KitchenSinkPlugin/src/KitchenSinkPlugin.cxx +++ b/GeoModelExamples/KitchenSinkPlugin/src/KitchenSinkPlugin.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ // ------------------------------------------------------------------- @@ -51,7 +51,7 @@ class KitchenSinkPlugin : public GeoVGeometryPlugin { ~KitchenSinkPlugin(); // Creation of geometry: - virtual void create(GeoPhysVol *world, bool publish=false); + virtual void create(GeoVPhysVol *world, bool publish=false); private: @@ -79,9 +79,8 @@ KitchenSinkPlugin::~KitchenSinkPlugin() // example (normally one may "publish" a list of FullPhysVol's and Alignable // transforms, but this example has none such). // -void KitchenSinkPlugin::create(GeoPhysVol *world, bool /*publish*/) -{ - const double degree=M_PI/180.0; +void KitchenSinkPlugin::create(GeoVPhysVol *world, bool /*publish*/) { + const double degree = M_PI / 180.0; // Define elements used in this example: GeoElement *oxygen = new GeoElement("Oxygen", "O", 19, 39*gram/mole); diff --git a/GeoModelExamples/MinimalPlugin/CMakeLists.txt b/GeoModelExamples/MinimalPlugin/CMakeLists.txt index 3b35d67b5339ae27a73cec14021d1fe0f8044987..f18dbe0f13576663c90929ba38bd2f2cc0ec258e 100644 --- a/GeoModelExamples/MinimalPlugin/CMakeLists.txt +++ b/GeoModelExamples/MinimalPlugin/CMakeLists.txt @@ -5,7 +5,7 @@ # author: Riccardo Maria BIANCHI @ CERN - May, 2022 ################################################################################ -cmake_minimum_required(VERSION 3.1.0) +cmake_minimum_required(VERSION 3.16...3.26) # Compile with C++17 set(CMAKE_CXX_STANDARD 17) diff --git a/GeoModelExamples/MinimalPlugin/src/MinimalPlugin.cxx b/GeoModelExamples/MinimalPlugin/src/MinimalPlugin.cxx index 41a3c4ef4de4331787ae1cedabcc55ca8c701e0f..e68834d6eeefe54eb80f72449ce5192e8b88657c 100644 --- a/GeoModelExamples/MinimalPlugin/src/MinimalPlugin.cxx +++ b/GeoModelExamples/MinimalPlugin/src/MinimalPlugin.cxx @@ -1,3 +1,7 @@ +/* + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration +*/ +#include "GeoModelKernel/GeoBox.h" #include "GeoModelKernel/GeoVGeometryPlugin.h" #include "GeoModelKernel/GeoDefinitions.h" #include "GeoModelKernel/GeoMaterial.h" @@ -18,7 +22,7 @@ class MinimalPlugin : public GeoVGeometryPlugin { ~MinimalPlugin(); // Creation of geometry: - virtual void create(GeoPhysVol *world, bool publish=false); + virtual void create(GeoVPhysVol *world, bool publish = false); private: @@ -46,9 +50,8 @@ MinimalPlugin::~MinimalPlugin() // example (normally one may "publish" a list of FullPhysVol's and Alignable // transforms, but this example has none such). // -void MinimalPlugin::create(GeoPhysVol *world, bool /*publish*/) -{ - const double degree=M_PI/180.0; +void MinimalPlugin::create(GeoVPhysVol *world, bool /*publish*/) { + const double degree = M_PI / 180.0; // Define elements used in this example: GeoElement *aluminium = new GeoElement("Aluminium", "Al", 13, 26 * GeoModelKernelUnits::g/GeoModelKernelUnits::mole); diff --git a/GeoModelExamples/NestedVolumes/CMakeLists.txt b/GeoModelExamples/NestedVolumes/CMakeLists.txt index b419eeb25027f0c2a5226a1d8c34806665544a0a..2d4b334ebe51b382ce4a55151f7aecbd490fef0b 100644 --- a/GeoModelExamples/NestedVolumes/CMakeLists.txt +++ b/GeoModelExamples/NestedVolumes/CMakeLists.txt @@ -5,7 +5,7 @@ # author: Riccardo Maria BIANCHI @ CERN - Nov, 2018 ################################################################################ -cmake_minimum_required(VERSION 3.1.0) +cmake_minimum_required(VERSION 3.16...3.26) #project(HelloGeoWrite) diff --git a/GeoModelExamples/NestedVolumes/README.md b/GeoModelExamples/NestedVolumes/README.md index f9d98f364d3ae07f54458cb6e3312559e0467d33..b269ee523aeb9c9d7e665e86f479683079d265a0 100644 --- a/GeoModelExamples/NestedVolumes/README.md +++ b/GeoModelExamples/NestedVolumes/README.md @@ -71,4 +71,4 @@ Now, you can **run the example** by typing: To build and run GeoModel I/O libraries, you must have a working Qt5 installation on your computer. Qt5 classes are used for I/O operations with the underlying SQLite daemon, to store/handle data, and to handle logging. -If you are not sure how to install it, please take a look at [the notes on Qt5, in the GeoModelIO repository](https://gitlab.cern.ch/GeoModelDev/GeoModelIO/blob/master/README_QT5_NOTES.md). +If you are not sure how to install it, please take a look at [the notes on Qt5, in the GeoModelIO repository](https://gitlab.cern.ch/GeoModelDev/GeoModelIO/blob/main/README_QT5_NOTES.md). diff --git a/GeoModelExamples/README.md b/GeoModelExamples/README.md index 0beeb964f69f99538f1e51cb197373261b79b724..f9e8747a33045815f347f627446491c9357ef34a 100644 --- a/GeoModelExamples/README.md +++ b/GeoModelExamples/README.md @@ -1,4 +1,4 @@ -[](https://gitlab.cern.ch/GeoModelDev/GeoModelExamples/commits/master) +[](https://gitlab.cern.ch/GeoModelDev/GeoModelExamples/commits/main) # GeoModelExamples @@ -91,4 +91,4 @@ You can visualize it by opening it with VP1Light. Please refer to the [Visualiza To build and run GeoModel I/O libraries, you must have a working Qt5 installation on your computer. Qt5 classes are used for I/O operations with the underlying SQLite daemon, to store/handle data, and to handle logging. -If you are not sure how to install it, please take a look at [the notes on Qt5, in the GeoModelIO repository](https://gitlab.cern.ch/GeoModelDev/GeoModelIO/blob/master/README_QT5_NOTES.md). +If you are not sure how to install it, please take a look at [the notes on Qt5, in the GeoModelIO repository](https://gitlab.cern.ch/GeoModelDev/GeoModelIO/blob/main/README_QT5_NOTES.md). diff --git a/GeoModelExamples/SharedNodes/CMakeLists.txt b/GeoModelExamples/SharedNodes/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..2a580301dd7b7cccee71bfb47010b9b46bf636f7 --- /dev/null +++ b/GeoModelExamples/SharedNodes/CMakeLists.txt @@ -0,0 +1,48 @@ +# Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration + +################################################################################ +# Package: HelloGeoWriteReadWrite +# author: Riccardo Maria BIANCHI @ CERN - May, 2022 +################################################################################ + +cmake_minimum_required(VERSION 3.1.0) + +project(SharedNodes) + +# Compile with C++17 +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS ON) + +if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) # when building individually + find_package( GeoModelCore REQUIRED ) + find_package( GeoModelIO REQUIRED ) +endif() + +# Find includes in current dir +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +# Populate a CMake variable with the sources +set(HDRS world.h) + +add_executable( test_shared_shapes shared_shapes.cpp ${HDRS} ) +target_link_libraries( test_shared_shapes GeoModelCore::GeoModelKernel GeoModelIO::GeoModelWrite GeoModelIO::GeoModelRead) + +add_executable( test_shared_logvols shared_logvols.cpp ${HDRS} ) +target_link_libraries( test_shared_logvols GeoModelCore::GeoModelKernel GeoModelIO::GeoModelWrite GeoModelIO::GeoModelRead) + +add_executable( test_shared_serialtransformers shared_serialtransformers.cpp ${HDRS} ) +target_link_libraries( test_shared_serialtransformers GeoModelCore::GeoModelKernel GeoModelIO::GeoModelWrite GeoModelIO::GeoModelRead) + +add_executable( test_shared_serialtransformers_2 shared_serialtransformers_2.cpp ${HDRS} ) +target_link_libraries( test_shared_serialtransformers_2 GeoModelCore::GeoModelKernel GeoModelIO::GeoModelWrite GeoModelIO::GeoModelRead) + +add_executable( test_shared_serialtransformers_3 shared_serialtransformers_3.cpp ${HDRS} ) +target_link_libraries( test_shared_serialtransformers_3 GeoModelCore::GeoModelKernel GeoModelIO::GeoModelWrite GeoModelIO::GeoModelRead) + +add_executable( test_shared_physvols shared_physvols.cpp ${HDRS} ) +target_link_libraries( test_shared_physvols GeoModelCore::GeoModelKernel GeoModelIO::GeoModelWrite GeoModelIO::GeoModelRead) + +add_executable( test_shared_nametags shared_nametags.cpp ${HDRS} ) +target_link_libraries( test_shared_nametags GeoModelCore::GeoModelKernel GeoModelIO::GeoModelWrite GeoModelIO::GeoModelRead) + diff --git a/GeoModelExamples/SharedNodes/README.md b/GeoModelExamples/SharedNodes/README.md new file mode 100644 index 0000000000000000000000000000000000000000..f9d98f364d3ae07f54458cb6e3312559e0467d33 --- /dev/null +++ b/GeoModelExamples/SharedNodes/README.md @@ -0,0 +1,74 @@ +# The 'helloGeoWrite' GeoModel example + +The `helloGeoWrite` example shows you how to create a simple geometry, by using GeoModel nodes. + +The example program: + + 1. Builds an example geometry: + 2. Writes the geometry to an SQLite file + 3. It accesses the persistent copy of the geometry, as a test + + +## Dependencies + +### Install Qt5 + +To build and run GeoModel I/O libraries, you must have a working Qt5 installation on your computer. +If you are not sure how to install it, please take a look at the Appendix, below. + + +#### GeoModelCore + +```bash +git clone ssh://git@gitlab.cern.ch:7999/GeoModelDev/GeoModelCore.git +mkdir build_gmcore +cd build_gmcore +cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=RelWithDebInfo ../GeoModelCore +make -j 4 +make install +cd .. +``` + +#### GeoModelIO + +```bash +git clone ssh://git@gitlab.cern.ch:7999/GeoModelDev/GeoModelIO.git +mkdir build_gmio +cd build_gmio +cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=RelWithDebInfo ../GeoModelIO +make -j 4 +make install +``` + + + +## Build + +From your work folder: + +```bash +git clone ssh://git@gitlab.cern.ch:7999/GeoModelDev/GeoModelExamples.git +mkdir build_hellogeo +cd build_hellogeo +cmake -DCMAKE_INSTALL_PREFIX=../install ../GeoModelExamples/HelloGeoWrite/ +make -j4 +``` + +## Run + +Now, you can **run the example** by typing: + +```bash +./hellogeoWrite +``` + + +---- + +## Appendix + +### Notes on Qt5 + +To build and run GeoModel I/O libraries, you must have a working Qt5 installation on your computer. Qt5 classes are used for I/O operations with the underlying SQLite daemon, to store/handle data, and to handle logging. + +If you are not sure how to install it, please take a look at [the notes on Qt5, in the GeoModelIO repository](https://gitlab.cern.ch/GeoModelDev/GeoModelIO/blob/master/README_QT5_NOTES.md). diff --git a/GeoModelExamples/SharedNodes/shared_logvols.cpp b/GeoModelExamples/SharedNodes/shared_logvols.cpp new file mode 100644 index 0000000000000000000000000000000000000000..eaa94c4cf866d64f23f4b415bd3e823b41a47e9c --- /dev/null +++ b/GeoModelExamples/SharedNodes/shared_logvols.cpp @@ -0,0 +1,97 @@ +// Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration + +/* + * This example tests shared LogVol nodes. + * + * It creates one single LogVol, with one Material and one Shape. + * Then it creates three PhysVol volumes using the above LogVol. + * + * It is meant to how how to share GeoModel nodes to reduce the memory footprint + * and to test the GeoModel I/O packages and methods. + * + * Author: Riccardo Maria BIANCHI @ CERN + * Created on: Dec, 2022 + * + */ + +// local includes +#include "world.h" + +// GeoModel includes +#include "GeoModelIOHelpers/GMIO.h" +#include "GeoModelIOHelpers/GMTests_IO.h" +#include "GeoModelKernel/GeoBox.h" +#include "GeoModelKernel/GeoFullPhysVol.h" +#include "GeoModelKernel/GeoNameTag.h" +#include "GeoModelKernel/GeoPhysVol.h" +#include "GeoModelKernel/GeoTube.h" + +// C++ includes +#include <cstdlib> // EXIT_FAILURE +#include <fstream> +#include <iostream> + +// Units +#include "GeoModelKernel/Units.h" +#define SYSTEM_OF_UNITS \ + GeoModelKernelUnits // so we will get, e.g., 'GeoModelKernelUnits::cm' + +int main(int argc, char *argv[]) { +// Define the units +#define gr SYSTEM_OF_UNITS::gram +#define mole SYSTEM_OF_UNITS::mole +#define cm3 SYSTEM_OF_UNITS::cm3 + + // get the World volume, + // we build it outside the class for convenience only + GeoPhysVol *world = GeoModel::World().getPhysVol(); + + // Define elements used in this example: + GeoElement *aluminium = + new GeoElement("Aluminium", "Al", 13, 26 * gr / mole); + GeoElement *iron = new GeoElement("Iron", "Fe", 26.0, 55.847 * gr / mole); + + // Define materials: + double densityOfAluminium = 2.7; // g/cm^3 + double densityOfIron = 7.87; // g/cm^3 + GeoMaterial *Aluminium = new GeoMaterial("Aluminium", densityOfAluminium); + Aluminium->add(aluminium, 1.0); + Aluminium->lock(); + + // define a shape node to share + const GeoTube *t1Tube = new GeoTube(0.5, 1.0, 2.0); + + // define two LogVol nodes that share the same shape + const GeoLogVol *t1Log = new GeoLogVol("T1Log", t1Tube, Aluminium); + + // build two PhysVol volumes with the two LogVol nodes + GeoPhysVol *t1Phys = new GeoPhysVol(t1Log); + GeoPhysVol *t2Phys = new GeoPhysVol(t1Log); + GeoPhysVol *t3Phys = new GeoPhysVol(t1Log); + + GeoTransform *xf2 = new GeoTransform(GeoTrf::Translate3D(-10.0, 0, 0)); + GeoTransform *xf3 = new GeoTransform(GeoTrf::Translate3D(10.0, 0, 0)); + + // add the first tube to the world + world->add(t1Phys); + + // add the second tube to the world + world->add(xf2); + world->add(t2Phys); + + // add the third tube to the world + world->add(xf3); + world->add(t3Phys); + + // --- I/O TESTS --- + std::cout << "\nTests:\n"; + unsigned loglevel = 0; + unsigned printtests = 1; + const bool forceDelete = true; + std::pair<bool, std::map<std::string, bool>> tests = + GeoModelIO::TestIO::runAllTests(world, loglevel, printtests, forceDelete); + bool testall = tests.first; + if (testall) return 0; + return 1; + // ---------------- +} diff --git a/GeoModelExamples/SharedNodes/shared_nametags.cpp b/GeoModelExamples/SharedNodes/shared_nametags.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3f534a305c7009eb7e2be381bad7efef59c4a895 --- /dev/null +++ b/GeoModelExamples/SharedNodes/shared_nametags.cpp @@ -0,0 +1,157 @@ +// Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration + +/* + * This example tests shared NameTag and SerialDenominator nodes. + * + * It creates one single LogVol, with one Material and one Shape. + * Then it creates three PhysVol volumes using the above LogVol. + * Then, one of those PhysVols is used to create children of the above volumes. + * + * This small application is meant to test the GeoModel I/O packages and methods + * on different nodes. + * + * Author: Riccardo Maria BIANCHI @ CERN + * Created on: Feb, 2023 + * + */ + +// local includes +#include "world.h" + +// GeoModel includes +#include "GeoModelIOHelpers/GMIO.h" +#include "GeoModelIOHelpers/GMTests_IO.h" + +// GeoModelKernel includes +#include "GeoModelKernel/GeoBox.h" +#include "GeoModelKernel/GeoNameTag.h" +#include "GeoModelKernel/GeoPhysVol.h" +#include "GeoModelKernel/GeoSerialDenominator.h" + +// C++ includes +#include <cstdlib> // EXIT_FAILURE +#include <fstream> +#include <iostream> + +// Units +#include "GeoModelKernel/Units.h" +#define SYSTEM_OF_UNITS \ + GeoModelKernelUnits // so we will get, e.g., 'GeoModelKernelUnits::cm' + +std::vector<std::string> testNTSD(const GeoVPhysVol *vol, std::string volname) { + std::vector<std::string> names; + std::cout << "Child volumes of '" << volname << "':\n"; + for (size_t id = 0; id < vol->getNChildVols(); ++id) { + std::string name = vol->getNameOfChildVol(id); + std::cout << "child [" << id << "] name: " << name << std::endl; + names.push_back(name); + } + return names; +} + +int main(int argc, char *argv[]) { +// Define the units +#define gr SYSTEM_OF_UNITS::gram +#define mole SYSTEM_OF_UNITS::mole +#define cm3 SYSTEM_OF_UNITS::cm3 + + // get the World volume, + // we build it outside the class for convenience only + GeoPhysVol *world = GeoModel::World().getPhysVol(); + + // Define elements used in this example: + GeoElement *aluminium = + new GeoElement("Aluminium", "Al", 13, 26 * gr / mole); + + // Define materials: + double densityOfAluminium = 2.7; // g/cm^3 + GeoMaterial *Aluminium = new GeoMaterial("Aluminium", densityOfAluminium); + Aluminium->add(aluminium, 1.0); + Aluminium->lock(); + + // define two shape nodes + const GeoBox *sh1 = new GeoBox(5.0, 5.0, 5.0); + const GeoBox *sh2 = new GeoBox(1.0, 1.0, 1.0); + + // define two LogVol nodes + const GeoLogVol *lv1 = new GeoLogVol("LVParent", sh1, Aluminium); + const GeoLogVol *lv2 = new GeoLogVol("LVChild", sh2, Aluminium); + + // build two PhysVol volumes with the two LogVol nodes + GeoPhysVol *pv1 = new GeoPhysVol(lv1); // parent volume + GeoPhysVol *pv2 = new GeoPhysVol(lv1); + GeoPhysVol *pv3 = new GeoPhysVol(lv1); + GeoPhysVol *pv4 = new GeoPhysVol(lv2); // child volume + + // create the transforms to place the parent volumes + GeoTransform *tr1 = new GeoTransform(GeoTrf::Translate3D(-15.0, 0, 0)); + GeoTransform *tr2 = new GeoTransform(GeoTrf::Translate3D(15.0, 0, 0)); + // create the transforms to place the child volumes inside the parent volume + GeoTransform *tr3 = new GeoTransform(GeoTrf::Translate3D(-3.0, 0, 0)); + GeoTransform *tr4 = new GeoTransform(GeoTrf::Translate3D(3.0, 0, 0)); + + // create a NameTag to share among the parent volumes + GeoNameTag *nt1 = new GeoNameTag("ParentVol"); + // create a SerialDenominator to incrementally name all child volumes of PV1 + // and PV3 + GeoSerialDenominator *sd1 = new GeoSerialDenominator("Child-"); + + // add the NameTag for the 1st parent volume to the world + world->add(nt1); + // add the first vol to the world, at 0,0,0 + world->add(pv1); + + // add the same vol to the world, but this time at -15,0,0 + world->add(tr1); + world->add(nt1); // NameTag for the 2nd parent vol + world->add(pv2); + + // add the same vol to the world, but this time at 15,0,0 + world->add(tr2); + world->add(nt1); // NameTag for the 3rd parent vol + world->add(pv3); + + // add the SerialDenominator to the parent volume, + // to name all children incrementally + pv1->add(sd1); + + // add the child volume to the PV1 volume, at 0,0,0 + pv1->add(pv4); + + // add the same child volume to the PV1 volume, at -3,0,0 + pv1->add(tr3); + pv1->add(pv4); + + // add the same child volume to the PV1 volume, at 3,0,0 + pv1->add(tr4); + pv1->add(pv4); + + // --- I/O TESTS --- + std::cout << "\nGeneral I/O Tests:\n"; + bool testall = GeoModelIO::TestIO::runAllTests(world, 0, 1, true).first; // we replace the existing .db file + // ---------------- + + // --- Specific NameTags and SerialDenominator tests --- + std::cout << "\nSpecific NameTags and SerialDenominator tests:\n"; + const std::string db1_name = "geometry_db_test_1.db"; + GeoModelIO::IO::saveToDB(world, db1_name, 0, true); // we write to a .db file replacing the existing file + const GeoVPhysVol *world2 = GeoModelIO::IO::loadDB(db1_name, 0); // we reload it + std::vector<std::string> t1 = testNTSD(world, "world"); + std::vector<std::string> t2 = testNTSD(pv1, "pv1"); + std::vector<std::string> t3 = testNTSD(world2, "world2"); + std::vector<std::string> t4 = + testNTSD(dynamic_cast<const GeoPhysVol *>(&(*(world2->getChildVol(0)))), + "pv1_2"); + bool tt1 = (t1 == t3); + bool tt2 = (t2 == t4); + testall = (testall && tt1 && tt2); + if (testall) + std::cout << "OK! Test of names passed.\n"; + else + std::cout << "ERROR! Test of names FAILED!!\n"; + // ---------------- + + // return 0 if all tests passed, returns 1 otherwise. + if (testall) return 0; + return 1; +} diff --git a/GeoModelExamples/SharedNodes/shared_physvols.cpp b/GeoModelExamples/SharedNodes/shared_physvols.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8a6ec5f220382a8afb63394c424724353dc3ccc0 --- /dev/null +++ b/GeoModelExamples/SharedNodes/shared_physvols.cpp @@ -0,0 +1,103 @@ +// Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration + +/* + * This example tests shared PhysVol nodes. + * + * It creates one single LogVol, with one Material and one Shape. + * Then it creates three PhysVol volumes using the above LogVol. + * Then, one of those PhysVols is used to create children of the above volumes. + * + * It is meant to how how to share GeoModel nodes to reduce the memory footprint + * and to test the GeoModel I/O packages and methods. + * + * Author: Riccardo Maria BIANCHI @ CERN + * Created on: Feb, 2023 + * + */ + +// local includes +#include "world.h" + +// GeoModel includes +#include "GeoModelIOHelpers/GMIO.h" +#include "GeoModelIOHelpers/GMTests_IO.h" +#include "GeoModelKernel/GeoBox.h" +#include "GeoModelKernel/GeoPhysVol.h" + +// C++ includes +#include <cstdlib> // EXIT_FAILURE +#include <fstream> +#include <iostream> + +// Units +#include "GeoModelKernel/Units.h" +#define SYSTEM_OF_UNITS \ + GeoModelKernelUnits // so we will get, e.g., 'GeoModelKernelUnits::cm' + +int main(int argc, char *argv[]) { +// Define the units +#define gr SYSTEM_OF_UNITS::gram +#define mole SYSTEM_OF_UNITS::mole +#define cm3 SYSTEM_OF_UNITS::cm3 + + // get the World volume, + // we build it outside the class for convenience only + GeoPhysVol *world = GeoModel::World().getPhysVol(); + + // Define elements used in this example: + GeoElement *aluminum = new GeoElement("Aluminum", "Al", 13, 26 * gr / mole); + + // Define materials: + double densityOfAluminum = 2.7; // g/cm^3 + GeoMaterial *Aluminum = new GeoMaterial("Aluminum", densityOfAluminum); + Aluminum->add(aluminum, 1.0); + Aluminum->lock(); + + // define two shape nodes + const GeoBox *sh1 = new GeoBox(5.0, 5.0, 5.0); + const GeoBox *sh2 = new GeoBox(1.0, 1.0, 1.0); + + // define two LogVol nodes + const GeoLogVol *lv1 = new GeoLogVol("LV1", sh1, Aluminum); + const GeoLogVol *lv2 = new GeoLogVol("LV2", sh2, Aluminum); + + // build two PhysVol volumes with the two LogVol nodes + GeoPhysVol *pv1 = new GeoPhysVol(lv1); // parent volume + GeoPhysVol *pv2 = new GeoPhysVol(lv2); // child volume + + // create the transforms to place the parent volumes + GeoTransform *tr1 = new GeoTransform(GeoTrf::Translate3D(-15.0, 0, 0)); + GeoTransform *tr2 = new GeoTransform(GeoTrf::Translate3D(15.0, 0, 0)); + // create the transforms to place the child volumes inside the parent volume + GeoTransform *tr3 = new GeoTransform(GeoTrf::Translate3D(-3.0, 0, 0)); + GeoTransform *tr4 = new GeoTransform(GeoTrf::Translate3D(3.0, 0, 0)); + + // add the first vol to the world, at 0,0,0 + world->add(pv1); + + // add the same vol to the world, but this time at -15,0,0 + world->add(tr1); + world->add(pv1); + + // add the same vol to the world, but this time at 15,0,0 + world->add(tr2); + world->add(pv1); + + // add the child volume to the PV1 volume, at 0,0,0 + pv1->add(pv2); + + // add the same child volume to the PV1 volume, at -3,0,0 + pv1->add(tr3); + pv1->add(pv2); + + // add the same child volume to the PV1 volume, at 3,0,0 + pv1->add(tr4); + pv1->add(pv2); + + // --- I/O TESTS --- + std::cout << "\nTests:\n"; + bool testall = GeoModelIO::TestIO::runAllTests(world, 0, 1, true).first; + if (testall) return 0; + return 1; + // ---------------- +} diff --git a/GeoModelExamples/SharedNodes/shared_serialtransformers.cpp b/GeoModelExamples/SharedNodes/shared_serialtransformers.cpp new file mode 100644 index 0000000000000000000000000000000000000000..240a10bfb50743874d42e58153b29d4c410cc668 --- /dev/null +++ b/GeoModelExamples/SharedNodes/shared_serialtransformers.cpp @@ -0,0 +1,166 @@ +// Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration + +/* + * This example tests shared GeoSerialTransformer nodes. + * + * It creates one single LogVol, with one Material and one Shape. + * Then it creates one single PhysVol volumes using the above LogVol. + * Then it creates three SerialTrasnformers with different placing formulas, + * but which share the same PhisVol defined above. + * + * It is meant to how how to share GeoModel nodes to reduce the memory footprint + * and to test the GeoModel I/O packages and methods. + * + * Author: Riccardo Maria BIANCHI @ CERN + * Created on: Dec, 2022 + * + */ + +// local includes +#include "world.h" + +// GeoModel includes +#include "GeoGenericFunctions/AbsFunction.h" +#include "GeoGenericFunctions/Cos.h" +#include "GeoGenericFunctions/Sin.h" +#include "GeoGenericFunctions/Variable.h" +#include "GeoModelDBManager/GMDBManager.h" +#include "GeoModelIOHelpers/GMIO.h" +#include "GeoModelIOHelpers/GMTests_IO.h" +#include "GeoModelKernel/GeoBox.h" +#include "GeoModelKernel/GeoFullPhysVol.h" +#include "GeoModelKernel/GeoPhysVol.h" +#include "GeoModelKernel/GeoSerialDenominator.h" +#include "GeoModelKernel/GeoSerialTransformer.h" +#include "GeoModelKernel/GeoTube.h" + +// C++ includes +#include <cstdlib> // EXIT_FAILURE +#include <fstream> +#include <iostream> + +// Units +#include "GeoModelKernel/Units.h" +#define SYSTEM_OF_UNITS \ + GeoModelKernelUnits // so we will get, e.g., 'GeoModelKernelUnits::cm' + +using namespace GeoGenfun; +using namespace GeoXF; + +int main(int argc, char *argv[]) { +// Define the units +#define gr SYSTEM_OF_UNITS::gram +#define mole SYSTEM_OF_UNITS::mole +#define cm3 SYSTEM_OF_UNITS::cm3 +#define degree SYSTEM_OF_UNITS::degree + + // get the World volume, + // we build it outside the class for convenience only + GeoPhysVol *world = GeoModel::World().getPhysVol(); + + // Define elements used in this example: + GeoElement *aluminum = new GeoElement("Aluminum", "Al", 13, 26 * gr / mole); + GeoElement *iron = new GeoElement("Iron", "Fe", 26.0, 55.847 * gr / mole); + + // Define materials: + double densityOfAluminum = 2.7; // g/cm^3 + double densityOfIron = 7.87; // g/cm^3 + GeoMaterial *Aluminum = new GeoMaterial("Aluminum", densityOfAluminum); + Aluminum->add(aluminum, 1.0); + Aluminum->lock(); + GeoMaterial *Iron = new GeoMaterial("Iron", densityOfIron); + Iron->add(iron, 1.0); + Iron->lock(); + + // define a container box + const GeoBox *toyBox = + new GeoBox(1200 * SYSTEM_OF_UNITS::cm, 1200 * SYSTEM_OF_UNITS::cm, + 1200 * SYSTEM_OF_UNITS::cm); + const GeoLogVol *toyLog = new GeoLogVol("ToyLog", toyBox, Aluminum); // + GeoPhysVol *toyPhys = new GeoPhysVol(toyLog); + + //--------------------------------------// + // Define some daughters and put them in the toy volume + //--------------------------------------// + const GeoTube *ringTube = + new GeoTube(500 * SYSTEM_OF_UNITS::cm, 1000 * SYSTEM_OF_UNITS::cm, + 5.0 * SYSTEM_OF_UNITS::cm); + const GeoLogVol *ringLog = new GeoLogVol("RingLog", ringTube, Aluminum); + // define a global name for the daughters + GeoSerialDenominator *ringName = new GeoSerialDenominator("RING"); + toyPhys->add(ringName); + // Make 100 of these // + // within the volume of the toy: // + for (int i = 0; i < 100; i++) { + GeoFullPhysVol *ringPhys = new GeoFullPhysVol(ringLog); + GeoAlignableTransform *xform = new GeoAlignableTransform( + GeoTrf::TranslateZ3D((i - 50) * 20 * SYSTEM_OF_UNITS::cm)); + toyPhys->add(xform); + toyPhys->add(ringPhys); + } + + //--------------------------------------// + // Now, in addition to active daughters, + // add some passive material. + // This is done here using + // the "SerialTransformer", + // our way of parameterizing volumes. + // It does not need to be done this way, + // but we want to provide an example of + // parametrizations in the Toy + //--------------------------------------// + + GeoBox *sPass = + new GeoBox(5.0 * SYSTEM_OF_UNITS::cm, 30 * SYSTEM_OF_UNITS::cm, + 30 * SYSTEM_OF_UNITS::cm); + GeoLogVol *lPass = new GeoLogVol("Passive", sPass, Iron); + GeoPhysVol *pPass = new GeoPhysVol(lPass); + + //--------------------------------------// + // Now, define two mathematical functions, + // which are used to parametrically place the volumes + // in space. + //--------------------------------------// + const unsigned int NPLATES = 100; + Variable i; + Sin sin; + GENFUNCTION f = 360 * SYSTEM_OF_UNITS::deg / NPLATES * i; + GENFUNCTION g = sin(4 * f); + GENFUNCTION h = -g; + TRANSFUNCTION t1 = Pow(GeoTrf::RotateZ3D(1.0), f) * + GeoTrf::TranslateX3D(1100 * SYSTEM_OF_UNITS::cm) * + Pow(GeoTrf::TranslateZ3D(800 * SYSTEM_OF_UNITS::cm), g); + TRANSFUNCTION t2 = Pow(GeoTrf::RotateZ3D(1.0), f) * + GeoTrf::TranslateX3D(1100 * SYSTEM_OF_UNITS::cm) * + Pow(GeoTrf::TranslateZ3D(800 * SYSTEM_OF_UNITS::cm), h); + + //--------------------------------------// + // Inside, by the way, the serial transformer + // will evaluate the functions: + // HepTransform3D xf = t1(i), for i=1,NPLATES.... + //--------------------------------------// + + GeoSerialDenominator *pass1Name = new GeoSerialDenominator("PASSIVE-1-"); + GeoSerialTransformer *s1 = new GeoSerialTransformer(pPass, &t1, NPLATES); + toyPhys->add(pass1Name); + toyPhys->add(s1); + + GeoSerialDenominator *pass2Name = new GeoSerialDenominator("PASSIVE-2-"); + GeoSerialTransformer *s2 = new GeoSerialTransformer(pPass, &t2, NPLATES); + toyPhys->add(pass2Name); + toyPhys->add(s2); + + world->add(toyPhys); + + // --- I/O TESTS --- + std::cout << "\nTests:\n"; + unsigned loglevel = 0; + unsigned printtests = 1; + const bool forceDelete = true; + std::pair<bool, std::map<std::string, bool>> tests = + GeoModelIO::TestIO::runAllTests(world, loglevel, printtests, forceDelete); + bool testall = tests.first; + if (testall) return 0; + return 1; + // ---------------- +} diff --git a/GeoModelExamples/SharedNodes/shared_serialtransformers_2.cpp b/GeoModelExamples/SharedNodes/shared_serialtransformers_2.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1f0ecc358860d092fc7507006f8f2fa610245945 --- /dev/null +++ b/GeoModelExamples/SharedNodes/shared_serialtransformers_2.cpp @@ -0,0 +1,168 @@ +// Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration + +/* + * This example tests shared GeoSerialTransformer nodes. + * + * In particular, it tests three serialtransformers that share a single PhysVol + * volume and a single Function. + * + * Author: Riccardo Maria BIANCHI @ CERN + * Created on: Feb, 2023 + * + */ + +// local includes +#include "world.h" + +// GeoModel includes +#include "GeoGenericFunctions/AbsFunction.h" +#include "GeoGenericFunctions/Cos.h" +#include "GeoGenericFunctions/Sin.h" +#include "GeoGenericFunctions/Variable.h" +#include "GeoModelDBManager/GMDBManager.h" +#include "GeoModelIOHelpers/GMIO.h" +#include "GeoModelIOHelpers/GMTests_IO.h" +#include "GeoModelKernel/GeoBox.h" +#include "GeoModelKernel/GeoFullPhysVol.h" +#include "GeoModelKernel/GeoPhysVol.h" +#include "GeoModelKernel/GeoSerialDenominator.h" +#include "GeoModelKernel/GeoSerialTransformer.h" +#include "GeoModelKernel/GeoTube.h" + +// C++ includes +#include <cstdlib> // EXIT_FAILURE +#include <fstream> +#include <iostream> + +// Units +#include "GeoModelKernel/Units.h" +#define SYSTEM_OF_UNITS \ + GeoModelKernelUnits // so we will get, e.g., 'GeoModelKernelUnits::cm' + +using namespace GeoGenfun; +using namespace GeoXF; + +int main(int argc, char *argv[]) { +// Define the units +#define gr SYSTEM_OF_UNITS::gram +#define mole SYSTEM_OF_UNITS::mole +#define cm3 SYSTEM_OF_UNITS::cm3 + + // get the World volume, + // we build it outside the class for convenience only + GeoPhysVol *world = GeoModel::World().getPhysVol(); + + // Define elements used in this example: + GeoElement *aluminum = new GeoElement("Aluminum", "Al", 13, 26 * gr / mole); + + // Define materials: + double densityOfAluminum = 2.7; // g/cm^3 + GeoMaterial *Aluminum = new GeoMaterial("Aluminum", densityOfAluminum); + Aluminum->add(aluminum, 1.0); + Aluminum->lock(); + + // define a container box + const GeoBox *toyBox = new GeoBox(20, 20, 20); + const GeoLogVol *toyLog = new GeoLogVol("ToyLog", toyBox, Aluminum); // + GeoPhysVol *toyPV = new GeoPhysVol(toyLog); + + // define the detector volumes + const GeoBox *sh1 = new GeoBox(1.0, 1.0, 1.0); + const GeoLogVol *lv1 = new GeoLogVol("LV1", sh1, Aluminum); + GeoPhysVol *pv1 = new GeoPhysVol(lv1); // parent volume + + //--------------------------------------// + // Now, define two mathematical functions, + // which are used to parametrically place the volumes + // in space. + //--------------------------------------// + const unsigned int NPLATES = 10; + Variable i; + Sin sin; + GENFUNCTION f = NPLATES * 2 * i; + GENFUNCTION g = sin(360 * SYSTEM_OF_UNITS::deg / NPLATES * i); + TRANSFUNCTION t1 = Pow(GeoTrf::TranslateX3D(1.0), f); + TRANSFUNCTION t2 = + Pow(GeoTrf::TranslateX3D(1.0), f) * Pow(GeoTrf::TranslateY3D(10.0), g); + + //--------------------------------------// + // Inside, by the way, the serial transformer + // will evaluate the functions: + // HepTransform3D xf = t1(i), for i=1,NPLATES.... + //--------------------------------------// + + GeoSerialDenominator *sd1 = new GeoSerialDenominator("PASSIVE-1-"); + GeoSerialTransformer *st1 = new GeoSerialTransformer(pv1, &t1, NPLATES); + toyPV->add(sd1); + toyPV->add(st1); + + GeoSerialDenominator *sd2 = new GeoSerialDenominator("PASSIVE-2-"); + GeoSerialTransformer *st2 = new GeoSerialTransformer(pv1, &t2, NPLATES); + toyPV->add(sd2); + toyPV->add(st2); + + GeoTransform *tr1 = new GeoTransform(GeoTrf::Translate3D(0, -30, 0)); + toyPV->add(tr1); + GeoSerialDenominator *sd3 = new GeoSerialDenominator("PASSIVE-3-"); + GeoSerialTransformer *st3 = new GeoSerialTransformer(pv1, &t2, NPLATES); + toyPV->add(sd3); + toyPV->add(st3); + + world->add(toyPV); + + // ===== TESTS ====== + bool alltests = false; + + // --- Manual tests --- + // Manually declare created objects, to test correctness of persistification + // of in-memory objects + std::map<std::string, unsigned long> nmap = GeoModelIO::IO::initNodesMap(); + nmap["Function"] = 2; // t1, t2 (f and g are persistified with t1 and t2) + nmap["PhysVol"] = 3; // world, toy, pv1 + nmap["LogVol"] = 3; // world, toy, lv1 + nmap["Shape"] = 3; // world, toy, lv1 + nmap["SerialTransformer"] = 3; // st1, st2, st3 + nmap["SerialDenominator"] = 3; // sd1, sd22, sd3 + nmap["Transform"] = 1; + nmap["Material"] = 2; // world::air, pv1::alu + nmap["Element"] = 5; // world::air (4), pv1::alu (1) + nmap["ChildrenConnections"] = + 8; // world->toy, toy->[sd1,st1,sd2,st2,tr1,sd3,st3] + + // get number of nodes from in-memory GeoModel through the Write action + std::map<std::string, unsigned long> memmap = + GeoModelIO::IO::countTreeMemoryNodesFromVolume(world); + // print the two maps + GeoModelIO::IO::printCompareTwoNodesMaps(nmap, memmap); + // compare the two maps + if (nmap == memmap) { + std::cout << "OK! Maps match.\n"; + alltests = true; + } else { + std::cout << "ERROR!!! Maps do NOT match!\n"; + alltests = false; + } + // --- Automated I/O TESTS --- + std::cout << "\nAutomated tests:\n"; + unsigned loglevel = 0; + unsigned printtests = 1; + const bool forceDelete = true; + std::pair<bool, std::map<std::string, bool>> tests = + GeoModelIO::TestIO::runAllTests(world, loglevel, printtests, forceDelete); + bool testall = tests.first; + if (testall) { + alltests = (alltests && testall); + } else { + alltests = false; + } + // ---------------- + std::cout << "\n\n***\n"; + if (alltests) { + std::cout << "OK! All tests PASSED.\n"; + return 0; + } else { + std::cout << "ERROR!!! Some tests did NOT pass!!!\n"; + return 1; + } + return 0; +} diff --git a/GeoModelExamples/SharedNodes/shared_serialtransformers_3.cpp b/GeoModelExamples/SharedNodes/shared_serialtransformers_3.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e955bdfa4deed31f5486eb35470153fa68aaa5b3 --- /dev/null +++ b/GeoModelExamples/SharedNodes/shared_serialtransformers_3.cpp @@ -0,0 +1,187 @@ +// Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration + +/* + * This example tests shared GeoSerialTransformer nodes. + * + * In particular, it tests three serialtransformers that share a single PhysVol + * volume and a single Function. + * + * Author: Riccardo Maria BIANCHI @ CERN + * Created on: Feb, 2023 + * + */ + +// local includes +#include "world.h" + +// GeoModel includes +#include "GeoGenericFunctions/AbsFunction.h" +#include "GeoGenericFunctions/Cos.h" +#include "GeoGenericFunctions/Sin.h" +#include "GeoGenericFunctions/Variable.h" +#include "GeoModelDBManager/GMDBManager.h" +#include "GeoModelIOHelpers/GMIO.h" +#include "GeoModelIOHelpers/GMTests_IO.h" +#include "GeoModelKernel/GeoBox.h" +#include "GeoModelKernel/GeoFullPhysVol.h" +#include "GeoModelKernel/GeoPhysVol.h" +#include "GeoModelKernel/GeoSerialDenominator.h" +#include "GeoModelKernel/GeoSerialTransformer.h" +#include "GeoModelKernel/GeoTube.h" + +// C++ includes +#include <cstdlib> // EXIT_FAILURE +#include <fstream> +#include <iostream> + +// Units +#include "GeoModelKernel/Units.h" +#define SYSTEM_OF_UNITS \ + GeoModelKernelUnits // so we will get, e.g., 'GeoModelKernelUnits::cm' + +using namespace GeoGenfun; +using namespace GeoXF; + +int main(int argc, char *argv[]) { +// Define the units +#define gr SYSTEM_OF_UNITS::gram +#define mole SYSTEM_OF_UNITS::mole +#define cm3 SYSTEM_OF_UNITS::cm3 + + // get the World volume, + // we build it outside the class for convenience only + GeoPhysVol *world = GeoModel::World().getPhysVol(); + + // Define elements used in this example: + GeoElement *aluminum = new GeoElement("Aluminum", "Al", 13, 26 * gr / mole); + + // Define materials: + double densityOfAluminum = 2.7; // g/cm^3 + GeoMaterial *Aluminum = new GeoMaterial("Aluminum", densityOfAluminum); + Aluminum->add(aluminum, 1.0); + Aluminum->lock(); + + // define a container box + const GeoBox *toyBox = new GeoBox(20, 20, 20); + const GeoLogVol *toyLog = new GeoLogVol("ToyLog", toyBox, Aluminum); // + GeoPhysVol *toyPV = new GeoPhysVol(toyLog); + + // define the detector volumes + const GeoBox *sh1 = new GeoBox(1.0, 1.0, 1.0); + const GeoLogVol *lv1 = new GeoLogVol("LV1", sh1, Aluminum); + GeoPhysVol *pv1 = new GeoPhysVol(lv1); // parent volume + + //--------------------------------------// + // Now, define two mathematical functions, + // which are used to parametrically place the volumes + // in space. + //--------------------------------------// + const unsigned int NPLATES = 10; + Variable i; + Sin sin; + GENFUNCTION f = NPLATES * 2 * i; + GENFUNCTION g = sin(360 * SYSTEM_OF_UNITS::deg / NPLATES * i); + TRANSFUNCTION t1 = Pow(GeoTrf::TranslateX3D(1.0), f); + TRANSFUNCTION t2 = + Pow(GeoTrf::TranslateX3D(1.0), f) * Pow(GeoTrf::TranslateY3D(10.0), g); + + //--------------------------------------// + // Inside, by the way, the serial transformer + // will evaluate the functions: + // HepTransform3D xf = t1(i), for i=1,NPLATES.... + //--------------------------------------// + + GeoSerialDenominator *sd1 = new GeoSerialDenominator("PASSIVE-1-"); + GeoSerialIdentifier *sid1 = new GeoSerialIdentifier(10); + GeoSerialTransformer *st1 = new GeoSerialTransformer(pv1, &t1, NPLATES); + toyPV->add(sd1); + toyPV->add(sid1); + toyPV->add(st1); + + GeoSerialDenominator *sd2 = new GeoSerialDenominator("PASSIVE-2-"); + GeoSerialIdentifier *sid2 = new GeoSerialIdentifier(20); + GeoSerialTransformer *st2 = new GeoSerialTransformer(pv1, &t2, NPLATES); + toyPV->add(sd2); + toyPV->add(sid2); + toyPV->add(st2); + + GeoTransform *tr1 = new GeoTransform(GeoTrf::Translate3D(0, -30, 0)); + toyPV->add(tr1); + GeoSerialDenominator *sd3 = new GeoSerialDenominator("PASSIVE-3-"); + GeoSerialTransformer *st3 = new GeoSerialTransformer(pv1, &t2, NPLATES); + toyPV->add(sd3); + toyPV->add(st3); + + GeoTransform *tr2 = new GeoTransform(GeoTrf::Translate3D(0, 30, 0)); + GeoIdentifierTag *id1 = new GeoIdentifierTag(1); + toyPV->add(tr2); + toyPV->add(id1); + toyPV->add(pv1); + + GeoTransform *tr3 = new GeoTransform(GeoTrf::Translate3D(0, 35, 0)); + GeoIdentifierTag *id2 = new GeoIdentifierTag(2); + toyPV->add(tr3); + toyPV->add(id2); + toyPV->add(pv1); + + world->add(toyPV); + + // ===== TESTS ====== + bool alltests = false; + + // --- Manual tests --- + // Manually declare created objects, to test correctness of persistification + // of in-memory objects + std::map<std::string, unsigned long> nmap = GeoModelIO::IO::initNodesMap(); + nmap["Function"] = 2; // t1, t2 (f and g are persistified with t1 and t2) + nmap["PhysVol"] = 3; // world, toy, pv1 + nmap["LogVol"] = 3; // world, toy, lv1 + nmap["Shape"] = 3; // world, toy, lv1 + nmap["SerialTransformer"] = 3; // st1, st2, st3 + nmap["SerialDenominator"] = 3; // sd1, sd22, sd3 + nmap["Transform"] = 3; // tr1, tr2, tr3 + nmap["Material"] = 2; // world::air, pv1::alu + nmap["Element"] = 5; // world::air (4), pv1::alu (1) + nmap["SerialIdentifier"] = 2; // sid1, sid2 + nmap["IdentifierTag"] = 2; // id1, id2 + nmap["ChildrenConnections"] = + 16; // world->toy, toy->[sd1,sid1,st1, sd2,sid2,st2, tr1,sd3,st3, + // tr2,id1,pv1, tr3,id2,pv1] + + // get number of nodes from in-memory GeoModel through the Write action + std::map<std::string, unsigned long> memmap = + GeoModelIO::IO::countTreeMemoryNodesFromVolume(world); + // print the two maps + GeoModelIO::IO::printCompareTwoNodesMaps(nmap, memmap); + // compare the two maps + if (nmap == memmap) { + std::cout << "OK! Maps match.\n"; + alltests = true; + } else { + std::cout << "ERROR!!! Maps do NOT match!\n"; + alltests = false; + } + // --- Automated I/O TESTS --- + std::cout << "\nAutomated tests:\n"; + unsigned loglevel = 0; + unsigned printtests = 1; + const bool forceDelete = true; + std::pair<bool, std::map<std::string, bool>> tests = + GeoModelIO::TestIO::runAllTests(world, loglevel, printtests, forceDelete); + bool testall = tests.first; + if (testall) { + alltests = (alltests && testall); + } else { + alltests = false; + } + // ---------------- + std::cout << "\n\n***\n"; + if (alltests) { + std::cout << "OK! All tests PASSED.\n"; + return 0; + } else { + std::cout << "ERROR!!! Some tests did NOT pass!!!\n"; + return 1; + } + return 0; +} diff --git a/GeoModelExamples/SharedNodes/shared_shapes.cpp b/GeoModelExamples/SharedNodes/shared_shapes.cpp new file mode 100644 index 0000000000000000000000000000000000000000..89cdfa324d764f9156bb104cce0a0fa1386af3eb --- /dev/null +++ b/GeoModelExamples/SharedNodes/shared_shapes.cpp @@ -0,0 +1,98 @@ +// Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration + +/* + * This example tests shared shapes. + * + * It creates one single GeoShape. + * Then it creates two LogVol nodes using the same GeoShape. + * Then it creates two PhysVol volumes using the two above LogVols. + * + * It is meant to how how to share GeoModel nodes to reduce the memory footprint + * and to test the GeoModel I/O packages and methods. + * + * Author: Riccardo Maria BIANCHI @ CERN + * Created on: Dec, 2022 + * + */ + +// local includes +#include "world.h" + +// GeoModel includes +#include "GeoModelIOHelpers/GMIO.h" +#include "GeoModelIOHelpers/GMTests_IO.h" +#include "GeoModelKernel/GeoBox.h" +#include "GeoModelKernel/GeoFullPhysVol.h" +#include "GeoModelKernel/GeoNameTag.h" +#include "GeoModelKernel/GeoPhysVol.h" +#include "GeoModelKernel/GeoTube.h" + +// C++ includes +#include <cstdlib> // EXIT_FAILURE +#include <fstream> +#include <iostream> + +// Units +#include "GeoModelKernel/Units.h" +#define SYSTEM_OF_UNITS \ + GeoModelKernelUnits // so we will get, e.g., 'GeoModelKernelUnits::cm' + +int main(int argc, char *argv[]) { +// Define the units +#define gr SYSTEM_OF_UNITS::gram +#define mole SYSTEM_OF_UNITS::mole +#define cm3 SYSTEM_OF_UNITS::cm3 + + // get the World volume, + // we build it outside the class for convenience only + GeoPhysVol *world = GeoModel::World().getPhysVol(); + + // Define elements used in this example: + GeoElement *aluminium = + new GeoElement("Aluminium", "Al", 13, 26 * gr / mole); + GeoElement *iron = new GeoElement("Iron", "Fe", 26.0, 55.847 * gr / mole); + + // Define materials: + double densityOfAluminium = 2.7; // g/cm^3 + double densityOfIron = 7.87; // g/cm^3 + GeoMaterial *Aluminium = new GeoMaterial("Aluminium", densityOfAluminium); + Aluminium->add(aluminium, 1.0); + Aluminium->lock(); + GeoMaterial *Iron = new GeoMaterial("Iron", densityOfIron); + Iron->add(iron, 1.0); + Iron->lock(); + + // define a shape node to share + const GeoTube *t1Tube = new GeoTube(0.5, 1.0, 2.0); + + // define two LogVol nodes that share the same shape + const GeoLogVol *t1Log = new GeoLogVol("T1Log", t1Tube, Aluminium); + const GeoLogVol *t2Log = new GeoLogVol("T2Log", t1Tube, Iron); + + // build two PhysVol volumes with the two LogVol nodes + GeoPhysVol *t1Phys = new GeoPhysVol(t1Log); + GeoPhysVol *t2Phys = new GeoPhysVol(t2Log); + + GeoTransform *xf1 = new GeoTransform(GeoTrf::Translate3D(-10.0, 0, 0)); + GeoTransform *xf2 = new GeoTransform(GeoTrf::Translate3D(10.0, 0, 0)); + + // add the first tube to the world + world->add(xf1); + world->add(t1Phys); + + // add the second tube to the world + world->add(xf2); + world->add(t2Phys); + + // --- I/O TESTS --- + std::cout << "\nTests:\n"; + unsigned loglevel = 0; + unsigned printtests = 1; + bool forceDelete = true; + std::pair<bool, std::map<std::string, bool>> tests = + GeoModelIO::TestIO::runAllTests(world, loglevel, printtests, forceDelete); + bool testall = tests.first; + if (testall) return 0; + return 1; + // ---------------- +} diff --git a/GeoModelExamples/SharedNodes/world.h b/GeoModelExamples/SharedNodes/world.h new file mode 100644 index 0000000000000000000000000000000000000000..1c5dd4cb0e33329864940cbcfb1cf76ea3b91a43 --- /dev/null +++ b/GeoModelExamples/SharedNodes/world.h @@ -0,0 +1,82 @@ + +// GeoModel includes +#include "GeoModelKernel/GeoBox.h" +#include "GeoModelKernel/GeoFullPhysVol.h" +#include "GeoModelKernel/GeoNameTag.h" +#include "GeoModelKernel/GeoPhysVol.h" +#include "GeoModelKernel/GeoTube.h" + +// Units +#include "GeoModelKernel/Units.h" +#define SYSTEM_OF_UNITS \ + GeoModelKernelUnits // so we will get, e.g., 'GeoModelKernelUnits::cm' +// Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration + +/* + * This class implements a default "World" volume. + * It can be used to contain other pieces of geometry. + * + * Author: Riccardo Maria BIANCHI @ CERN + * Created on: Dec, 2022 + * + */ +// C++ includes +#include <iostream> + +namespace GeoModel { + +class World { + public: + World() { + //-----------------------------------------------------------------------------------// + // Define the materials that we shall use. // + // ----------------------------------------------------------------------------------// + +// Define the units +#define gr SYSTEM_OF_UNITS::gram +#define mole SYSTEM_OF_UNITS::mole +#define cm3 SYSTEM_OF_UNITS::cm3 + + // Define the chemical elements + GeoElement* Nitrogen = + new GeoElement("Nitrogen", "N", 7.0, 14.0067 * gr / mole); + GeoElement* Oxygen = + new GeoElement("Oxygen", "O", 8.0, 15.9995 * gr / mole); + GeoElement* Argon = + new GeoElement("Argon", "Ar", 18.0, 39.948 * gr / mole); + GeoElement* Hydrogen = + new GeoElement("Hydrogen", "H", 1.0, 1.00797 * gr / mole); + + // Define the materials + + double densityOfAir = 0.001214 * gr / cm3; + GeoMaterial* air = new GeoMaterial("Air", densityOfAir); + air->add(Nitrogen, 0.7494); + air->add(Oxygen, 0.2369); + air->add(Argon, 0.0129); + air->add(Hydrogen, 0.0008); + air->lock(); + + //-----------------------------------------------------------------------------------// + // create the world volume container and + // get the 'world' volume, i.e. the root volume of the GeoModel tree + std::cout << "Creating the 'world' volume, i.e. the root volume of the " + "GeoModel tree..." + << std::endl; + const GeoBox* worldBox = + new GeoBox(1000 * SYSTEM_OF_UNITS::cm, 1000 * SYSTEM_OF_UNITS::cm, + 1000 * SYSTEM_OF_UNITS::cm); + const GeoLogVol* worldLog = new GeoLogVol("WorldLog", worldBox, air); + GeoPhysVol* world = new GeoPhysVol(worldLog); + m_pv = world; + } + + GeoPhysVol* getPhysVol() { return m_pv; } + + private: + GeoPhysVol* m_pv; + +}; // close class + +} // namespace GeoModel + diff --git a/GeoModelG4/CMakeLists.txt b/GeoModelG4/CMakeLists.txt index 128f647f3b4d3215e7777e83194b51e05844144a..c8f4e326e67125911781c543f7f7ee7f103d0849 100644 --- a/GeoModelG4/CMakeLists.txt +++ b/GeoModelG4/CMakeLists.txt @@ -1,19 +1,17 @@ # Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration # CMake settings -cmake_minimum_required( VERSION 3.14 ) +cmake_minimum_required(VERSION 3.16...3.26) -# Dummy call to 'project()', needed to set 'PROJECT_SOURCE_DIR' -project( "GeoModelG4" ) #Set up the project. Check if we build it with GeoModel or individually -if( (CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) OR GEOMODEL_BUILD_GEOMODELG4_FROM_FULLSIMLIGHT ) +if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) # I am top-level project. # Make the root module directory visible to CMake. list( APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../cmake ) # get global GeoModel version include( GeoModel-version ) # set the project, with the version taken from the GeoModel parent project - project( "GeoModelG4" VERSION ${GeoModel_VERSION} LANGUAGES CXX ) + project( GeoModelG4 VERSION ${GeoModel_VERSION} LANGUAGES CXX ) # Define color codes for CMake messages include( cmake_colors_defs ) # Warn the users about what they are doing @@ -22,33 +20,24 @@ if( (CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) OR GEOMODEL_BUILD_GEOMODELG4_ include( BuildType ) # Set default build and C++ options include( configure_cpp_options ) - set( CMAKE_FIND_FRAMEWORK "LAST" CACHE STRING - "Framework finding behaviour on macOS" ) + set( CMAKE_FIND_FRAMEWORK "LAST" CACHE STRING "Framework finding behaviour on macOS" ) # Find the base GeoModel packages, which must be installed on the target system already find_package( GeoModelCore REQUIRED ${GeoModel_VERSION} ) - # Find Geant4, if not triggered by FullSimLight, where Geant4 is already found/set. - if( NOT GEOMODEL_BUILD_GEOMODELG4_FROM_FULLSIMLIGHT ) - find_package( Geant4 REQUIRED ) - include( SetupXercesC ) - endif() - # Set a flag to steer the of the subpackages - set( ${PROJECT_NAME}_INDIVIDUAL_BUILD ON ) # Print Build Info on screen include( PrintBuildInfo ) else() # I am called from other projects with add_subdirectory(). message( STATUS "Building ${PROJECT_NAME} as part of the root GeoModel project.") # Set the project - project( "GeoModelG4" VERSION ${GeoModel_VERSION} LANGUAGES CXX ) - # External dependencies: - find_package( Geant4 REQUIRED ) + project( GeoModelG4 VERSION ${GeoModel_VERSION} LANGUAGES CXX ) endif() +find_package( Geant4 REQUIRED ) + # Set up the build of the three libraries of the project. add_subdirectory(GeoMaterial2G4) add_subdirectory(GeoModel2G4) - install(EXPORT GeoMaterial2G4-export FILE GeoModelG4-GeoMaterial2G4.cmake DESTINATION lib/cmake/GeoModelG4) install(EXPORT GeoModel2G4-export FILE GeoModelG4-GeoModel2G4.cmake DESTINATION lib/cmake/GeoModelG4) install(FILES cmake/GeoModelG4Config.cmake DESTINATION lib/cmake/GeoModelG4) diff --git a/GeoModelG4/GeoMaterial2G4/CMakeLists.txt b/GeoModelG4/GeoMaterial2G4/CMakeLists.txt index 9cf118c6b32f203c486757cc87fe5f139d35f521..434517536511f6643d7b0710f41d3d909cf982fc 100644 --- a/GeoModelG4/GeoMaterial2G4/CMakeLists.txt +++ b/GeoModelG4/GeoMaterial2G4/CMakeLists.txt @@ -3,8 +3,8 @@ ################################################################################ # Package: GeoMaterial2G4 ################################################################################ -cmake_minimum_required(VERSION 3.10) -project( "GeoMaterial2G4" VERSION ${GeoModel_VERSION} LANGUAGES CXX ) +cmake_minimum_required(VERSION 3.16...3.26) +project(GeoMaterial2G4 VERSION ${GeoModel_VERSION} LANGUAGES CXX) # Use the GNU install directory names. include( GNUInstallDirs ) # it defines CMAKE_INSTALL_LIBDIR @@ -13,38 +13,23 @@ include( GNUInstallDirs ) # it defines CMAKE_INSTALL_LIBDIR file( GLOB SOURCES src/*.cxx ) file( GLOB HEADERS GeoMaterial2G4/*.h ) -# include Geant4 headers -include(${Geant4_USE_FILE}) - # Set target and properties add_library( GeoMaterial2G4 SHARED ${HEADERS} ${SOURCES} ) -# If the in-house build of the nlohmann_json library is used, add explicit dependency -if( GEOMODEL_USE_BUILTIN_XERCESC ) - add_dependencies( GeoMaterial2G4 XercesCBuiltIn ) -endif() -# Check if we are building FullSimLight individually, -# or as a part of the main GeoModel. -# In the first case, we link against the imported targets, which are taken -# from the base GeoModel packages already installed on the system. -# This is used when building distribution packages. -if ( GeoModelG4_INDIVIDUAL_BUILD ) # if built individually - target_link_libraries( GeoMaterial2G4 PUBLIC GeoModelCore::GeoModelKernel ) -else() - target_link_libraries( GeoMaterial2G4 PUBLIC GeoModelKernel ) -endif() -target_link_libraries( GeoMaterial2G4 PUBLIC ${Geant4_LIBRARIES} ) - -target_include_directories( GeoMaterial2G4 PUBLIC - $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> - $<INSTALL_INTERFACE:include> ) +target_include_directories( GeoMaterial2G4 + PUBLIC + $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> + $<INSTALL_INTERFACE:include> ) +target_link_libraries( GeoMaterial2G4 PUBLIC GeoModelCore::GeoModelKernel ${Geant4_LIBRARIES} ) # Set installation of library headers set_property( TARGET GeoMaterial2G4 PROPERTY PUBLIC_HEADER ${HEADERS} ) set_target_properties( GeoMaterial2G4 PROPERTIES - VERSION ${PROJECT_VERSION} - SOVERSION ${PROJECT_VERSION_MAJOR} ) + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR} ) # new test GeoModelG4 -install( TARGETS GeoMaterial2G4 EXPORT GeoMaterial2G4-export LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} +install(TARGETS GeoMaterial2G4 + EXPORT GeoMaterial2G4-export + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/GeoMaterial2G4 ) diff --git a/GeoModelG4/GeoModel2G4/CMakeLists.txt b/GeoModelG4/GeoModel2G4/CMakeLists.txt index df227e6de95a31ba83546887e83bdac3db111a4f..143c8f22d13601e4337dce75e1a6285378aa7727 100644 --- a/GeoModelG4/GeoModel2G4/CMakeLists.txt +++ b/GeoModelG4/GeoModel2G4/CMakeLists.txt @@ -4,10 +4,10 @@ # Package: GeoModel2G4 ################################################################################ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16...3.26) # Declare the package name -project( "GeoModel2G4" VERSION ${GeoModel_VERSION} LANGUAGES CXX ) +project(GeoModel2G4 VERSION ${GeoModel_VERSION} LANGUAGES CXX) ########################################################## # NOTE! The original package also needs this Athena stuff: @@ -28,34 +28,20 @@ include( GNUInstallDirs ) # it defines CMAKE_INSTALL_LIBDIR file( GLOB SOURCES src/*.cxx ) file( GLOB HEADERS GeoModel2G4/*.h ) -# include Geant4 headers -include(${Geant4_USE_FILE}) - # set the path where the G4 extensions are found (e.g., the LArCustomSolid ATLAS extension) set(PATHEXTENSIONS ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR} ) -add_definitions (-DG4EXTENSION_SOLID_DIR=${PATHEXTENSIONS}) message("==> NOTE: G4 solid extensions will be searched in: ${PATHEXTENSIONS}. If you need custom extensions check if this is the right path. If not, set the right path by setting the environmental variable 'G4EXTENSION_SOLID_DIR' before running the application that uses the GeoModel2G4 library (e.g., 'export G4EXTENSION_SOLID_DIR=/usr/local/Cellar/geomodel-extension-atlaslar/5.4.0/lib') " ) # Set target and properties -add_library( GeoModel2G4 SHARED ${HEADERS} ${SOURCES} ) -target_link_libraries( GeoModel2G4 - PUBLIC ${GEANT4_LIBRARIES} - PRIVATE GeoMaterial2G4 ) -# Check if we are building FullSimLight individually, -# or as a part of the main GeoModel. -# In the first case, we link against the imported targets, which are taken -# from the base GeoModel packages already installed on the system.^[OB -# This is used when building distribution packages. -if ( GeoModelG4_INDIVIDUAL_BUILD ) # if built individually - target_link_libraries( GeoModel2G4 PRIVATE GeoModelCore::GeoModelKernel ) -else() - target_link_libraries( GeoModel2G4 PRIVATE GeoModelKernel ) -endif() - -target_include_directories( GeoModel2G4 SYSTEM PUBLIC ${GEANT4_INCLUDE_DIRS} ) -target_include_directories( GeoModel2G4 PUBLIC - $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> - $<INSTALL_INTERFACE:include> ) +add_library(GeoModel2G4 SHARED ${HEADERS} ${SOURCES}) +target_compile_definitions(GeoModel2G4 PRIVATE G4EXTENSION_SOLID_DIR=${PATHEXTENSIONS}) +target_include_directories(GeoModel2G4 + PUBLIC + $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> + $<INSTALL_INTERFACE:include> ) +target_link_libraries(GeoModel2G4 + PUBLIC ${Geant4_LIBRARIES} + PRIVATE GeoMaterial2G4 GeoModelCore::GeoModelKernel) # Set installation of library headers set_property( TARGET GeoModel2G4 PROPERTY PUBLIC_HEADER ${HEADERS} ) @@ -65,5 +51,7 @@ set_target_properties( GeoModel2G4 PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR} ) # Install the library. -install( TARGETS GeoModel2G4 EXPORT GeoModel2G4-export LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} +install( TARGETS GeoModel2G4 + EXPORT GeoModel2G4-export + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/GeoModel2G4 ) diff --git a/GeoModelG4/GeoModel2G4/GeoModel2G4/ExtParameterisedVolumeBuilder.h b/GeoModelG4/GeoModel2G4/GeoModel2G4/ExtParameterisedVolumeBuilder.h index 40046b52c2a3840b6c607f03f203b0aa118cb27f..1b95bd5c908b34bff3560d2bdb13327cf946aa43 100644 --- a/GeoModelG4/GeoModel2G4/GeoModel2G4/ExtParameterisedVolumeBuilder.h +++ b/GeoModelG4/GeoModel2G4/GeoModel2G4/ExtParameterisedVolumeBuilder.h @@ -17,9 +17,9 @@ class ExtParameterisedVolumeBuilder: public VolumeBuilder public: ExtParameterisedVolumeBuilder(std::string n); /// - G4LogicalVolume* Build(GeoPVConstLink pv) const; + G4LogicalVolume* Build(PVConstLink pv) const; /// - Geo2G4AssemblyVolume* BuildAssembly(GeoPVConstLink pv) const; + Geo2G4AssemblyVolume* BuildAssembly(PVConstLink pv) const; private: /// Prints info when some PhysVol contains both types (PV and ST) of daughters void PrintSTInfo(std::string volume) const; diff --git a/GeoModelG4/GeoModel2G4/GeoModel2G4/VolumeBuilder.h b/GeoModelG4/GeoModel2G4/GeoModel2G4/VolumeBuilder.h index 4fc98f05631a483e816e3d9d84877b28a7a4074d..d60d57447ec40025fd26214019afd5ed75f0d74d 100644 --- a/GeoModelG4/GeoModel2G4/GeoModel2G4/VolumeBuilder.h +++ b/GeoModelG4/GeoModel2G4/GeoModel2G4/VolumeBuilder.h @@ -1,13 +1,12 @@ /* - Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #ifndef GEO2G4_VolumeBuilder_H #define GEO2G4_VolumeBuilder_H #include "G4LogicalVolume.hh" -//#include "Geo2G4SvcAccessor.h" -//#include "GeoModelUtilities/GeoOpticalPhysVol.h" +#include "GeoModelKernel/GeoVPhysVol.h" #include "G4VPhysicalVolume.hh" @@ -17,7 +16,6 @@ //typedef std::map< const GeoOpticalPhysVol*, G4VPhysicalVolume*,std::less< const GeoOpticalPhysVol*> > OpticalVolumesMap; -class GeoPVConstLink; class VolumeBuilder { public: @@ -36,7 +34,7 @@ class VolumeBuilder bool GetParam(){return m_paramOn;} //virtual G4LogicalVolume* Build(PVConstLink pv, OpticalVolumesMap* optical_volumes = 0) const = 0; - virtual G4LogicalVolume* Build(GeoPVConstLink pv) const = 0; + virtual G4LogicalVolume* Build(PVConstLink pv) const = 0; protected: bool m_paramOn; diff --git a/GeoModelG4/GeoModel2G4/original_GeoModel2G4/CMakeLists.txt b/GeoModelG4/GeoModel2G4/original_GeoModel2G4/CMakeLists.txt index 293f17da2fa8af029d7bb596fc8b193717b76c7f..55c9883f6043b6465bd87306a6c547808d61c887 100644 --- a/GeoModelG4/GeoModel2G4/original_GeoModel2G4/CMakeLists.txt +++ b/GeoModelG4/GeoModel2G4/original_GeoModel2G4/CMakeLists.txt @@ -2,7 +2,7 @@ # Package: Geo2G4 ################################################################################ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16...3.26) # Declare the package name project( "Geo2G4" VERSION 1.0.0 LANGUAGES CXX ) diff --git a/GeoModelIO/CMakeLists.txt b/GeoModelIO/CMakeLists.txt index a16e62b01ab53521da03edbddd53321f241bea07..fb4ac93e4853f04b52f6b69e0c6ec4bf944fa5ad 100644 --- a/GeoModelIO/CMakeLists.txt +++ b/GeoModelIO/CMakeLists.txt @@ -9,6 +9,7 @@ add_subdirectory( GeoModelDBManager ) add_subdirectory( TFPersistification ) add_subdirectory( GeoModelRead ) add_subdirectory( GeoModelWrite ) +add_subdirectory( GeoModelIOHelpers ) # Create and install the version description of the project. include( CMakePackageConfigHelpers ) diff --git a/GeoModelIO/GeoModelDBManager/CMakeLists.txt b/GeoModelIO/GeoModelDBManager/CMakeLists.txt index 5bc09043fef3853c4d51212b5279a8d48ee79b4f..7eb42f1af7a018644585e7a19c7d59f74234d598 100644 --- a/GeoModelIO/GeoModelDBManager/CMakeLists.txt +++ b/GeoModelIO/GeoModelDBManager/CMakeLists.txt @@ -37,3 +37,8 @@ install(TARGETS GeoModelDBManager install( FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/GeoModelDBManager COMPONENT Development ) + +add_executable(test_create_db_file tests/test_create_db_file.cpp) +target_link_libraries( test_create_db_file GeoModelIO::GeoModelDBManager) +add_test(NAME TestCreateDBFile + COMMAND test_create_db_file) diff --git a/GeoModelIO/GeoModelDBManager/GeoModelDBManager/GMDBManager.h b/GeoModelIO/GeoModelDBManager/GeoModelDBManager/GMDBManager.h index ce4ff886127aadd7584a48887b4419c3a72512ef..e239ec1147457e06c2da5763cb79d232a440c9e2 100644 --- a/GeoModelIO/GeoModelDBManager/GeoModelDBManager/GMDBManager.h +++ b/GeoModelIO/GeoModelDBManager/GeoModelDBManager/GMDBManager.h @@ -189,8 +189,16 @@ class GMDBManager { void printAllDBTables(); + /// Get tables and tables' columns from the input DB, if any, + /// and populate the cache that stores them void createTableDataCaches(); + + /// Get all tables from the input DB, if any, + /// and populate the cache that stores them void getAllDBTables(); + + /// Get tables' columns from the input DB, if any, + /// and populate the cache that stores them void getAllDBTableColumns(); int execQuery(std::string queryStr); @@ -247,6 +255,12 @@ class GMDBManager { /// methods to dump the DB std::vector<std::vector<std::string>> getChildrenTable(); + // Table names for Aux tables are of the form prefix_suffix + // where prefix depends on the type of data in the table + // and suffix depends on the plugin/publisher that provided it + + // These two require only the suffix, the prefix is already specified based + // on the table type being accessed std::vector<std::vector<std::string>> getPublishedFPVTable( std::string suffix = ""); std::vector<std::vector<std::string>> getPublishedAXFTable( @@ -261,6 +275,10 @@ class GMDBManager { std::vector<std::vector<std::string>> getTableRecords( std::string tableName) const; // TODO: should be private? + // Test if a given table exists + // This requires the *full* table name (i.e. prefix_suffix) + bool checkTable(std::string tableName) const; + /** * @brief Create a custom DB table to store auxiliary data. * @param tableName The name of the custom table @@ -278,6 +296,9 @@ class GMDBManager { const std::vector< std::vector<std::variant<int, long, float, double, std::string>>> &records); + + + unsigned int getTableIdFromNodeType(const std::string &nodeType); // bool createCustomTable(const std::string tableName, const // std::vector<std::string> tableColNames, const std::vector<std::string> // tableColTypes, const std::vector<std::vector<std::string>> &records ); // @@ -315,7 +336,6 @@ class GMDBManager { std::string getTableNameFromTableId(unsigned int tabId); - unsigned int getTableIdFromNodeType(const std::string &nodeType); void storeNodeType(std::string nodeType, std::string tableName); std::string getTableNameFromNodeType(const std::string &nodeType); @@ -338,12 +358,14 @@ class GMDBManager { // verbosity level int m_verbose; - std::unordered_map<std::string, std::vector<std::string>> - m_tableNames; /// stores the column names for each table + /// stores the column names for each table + std::unordered_map<std::string, std::vector<std::string>> m_tableNames; + std::unordered_map<std::string, std::string> m_childType_tableName; - std::vector<std::string> - m_cache_tables; /// cache for the list of tables in the DB + /// cache for the list of tables in the DB + std::vector<std::string> m_cache_tables; + std::unordered_map<unsigned int, std::string> m_cache_tableId_tableName; /// cache for tableID-->tableName std::unordered_map<unsigned int, std::string> diff --git a/GeoModelIO/GeoModelDBManager/src/GMDBManager.cpp b/GeoModelIO/GeoModelDBManager/src/GMDBManager.cpp index 4940ac06c912aacbc56f409ce7edfe8c54ae526a..66e0218c31554d8e46673dabf9e5e073d64c1531 100644 --- a/GeoModelIO/GeoModelDBManager/src/GMDBManager.cpp +++ b/GeoModelIO/GeoModelDBManager/src/GMDBManager.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ /* @@ -8,9 +8,12 @@ * - Aug 2018, R.M.Bianchi * - Jun 2020, R.M.Bianchi * - Aug 2020, R.M.Bianchi - Added support to publish lists of FullPhysVol and - * AlignableTransform nodes + * AlignableTransform nodes * - Jun 2022 - Riccardo Maria Bianchi, <riccardo.maria.bianchi@cern.ch>, * Added support for "Verbose" output + * - Jul 2023 - Riccardo Maria Bianchi, <riccardo.maria.bianchi@cern.ch>, + * Populate the caches in the constructor, so all print methods are + * available as soon as the input file is opened by the GMDBManager */ #include <GeoModelDBManager/GMDBManager.h> @@ -83,6 +86,7 @@ class GMDBManager::Imp { sqlite3_stmt* selectAllFromTableSortBy(std::string tableName, std::string sortColumn = "") const; sqlite3_stmt* selectAllFromTableChildrenPositions() const; + bool checkTable_imp(std::string tableName) const; }; GMDBManager::GMDBManager(const std::string& path) @@ -98,7 +102,9 @@ GMDBManager::GMDBManager(const std::string& path) m_dbIsOK = false; // FIXME: TODO: we should check the existence of the file, otherwise SQLite - // will create a new file from scratch Save the connection result + // will create a new file from scratch + + // Save the connection result int exit = sqlite3_open(path.c_str(), &m_d->m_dbSqlite); // Test if there was an error @@ -120,16 +126,12 @@ GMDBManager::GMDBManager(const std::string& path) m_verbose = std::stoi(env_p); } - // if (m_dbIsOK) { - // if ( ! (initDB()) ) { - // std::cout << "Error: database initialization failed" << std::endl; - // m_dbIsOK = false; - // } - // } - - // populate DB with fake data, only for debug - // loadTestData(); // TODO: we should move initDB() here, only for debug and - // Write + /// get info from the input DB, if populated, + /// and create caches storing those pieces of information + /// This call is only useful when reading an existing DB file. + /// If the file is new (that is, when we use GMDBManager to write a piece of + /// geometry into a new file, the call below does nothing. + createTableDataCaches(); } GMDBManager::~GMDBManager() { @@ -206,7 +208,7 @@ void GMDBManager::createTableDataCaches() { void GMDBManager::printAllRecords(const std::string& tableName) const { // --- print table name - std::cout << "\n---" << std::endl; + std::cout << "---" << std::endl; std::cout << "'" << tableName << "' in db:" << std::endl; // --- check if we stored table's data if (m_tableNames.find(tableName) == m_tableNames.end()) { @@ -231,13 +233,13 @@ void GMDBManager::printAllRecords(const std::string& tableName) const { } } std::cout << "---" << std::endl; - // TODO: I want to have a symbol like '---' to mean empty line when query - // gives 0 results. + // TODO: I want to have a symbol like '---' to mean empty line when + // query gives 0 results. } -// FIXME: TODO: we now return all records as text, but should we get double/int -// instead when appropriate? In that case, we should create dedicated methods -// for all tables, I guess. +// FIXME: TODO: we now return all records as text, but should we get +// double/int instead when appropriate? In that case, we should create +// dedicated methods for all tables, I guess. // TODO: fill a cache and returns that if asked a second time std::vector<std::vector<std::string>> GMDBManager::getTableRecords( std::string tableName) const { @@ -245,6 +247,7 @@ std::vector<std::vector<std::string>> GMDBManager::getTableRecords( std::vector<std::vector<std::string>> records; // get the query statetement ready to be executed sqlite3_stmt* stmt = nullptr; + if ("ChildrenPositions" == tableName) { stmt = m_d->selectAllFromTableChildrenPositions(); } else { @@ -259,16 +262,17 @@ std::vector<std::vector<std::string>> GMDBManager::getTableRecords( res = sqlite3_step(stmt); // Execute SQL Statement. if (res == SQLITE_ROW) { std::vector<std::string> - nodeParams; // stores the data items contained in a single - // row + nodeParams; // stores the data items contained in a + // single row for (int i = 0; i < ctotal; i++) // Loop times the number of columns in the table { std::string s; const char* cc = (char*)sqlite3_column_text( - stmt, i); // Read each Column in the row as text FIXME: - // is there a method to get the right type, - // e.g. double, instead of text? + stmt, + i); // Read each Column in the row as text FIXME: + // is there a method to get the right type, + // e.g. double, instead of text? if (cc == NULL) s = "NULL"; else @@ -301,9 +305,12 @@ std::vector<std::vector<std::string>> GMDBManager::getTableFromNodeType( std::mutex coutMutex; coutMutex.lock(); printf( - "\t ===> WARNING! The geometry input file does not contain a table " - "for the %s nodes. That means that you are probably using an old " - "geometry file. Unless you know exactly what you are doing, please " + "\t ===> WARNING! The geometry input file does not contain a " + "table " + "for the %s nodes. That means that you are probably using an " + "old " + "geometry file. Unless you know exactly what you are doing, " + "please " "expect to see incomplete geometries or crashes.\n", nodeType.c_str()); coutMutex.unlock(); @@ -326,8 +333,8 @@ bool GMDBManager::addListOfChildrenPositions( // NOTE: Choose the right function for your version of SQLite!! return addListOfRecordsToTable("ChildrenPositions", records); // needs SQLite >= 3.7.11 - // return addListOfRecordsToTableOld("ChildrenPositions", records); // - // old SQLite versions + // return addListOfRecordsToTableOld("ChildrenPositions", records); + // // old SQLite versions } return false; } @@ -344,16 +351,16 @@ bool GMDBManager::addListOfPublishedAlignableTransforms( tableName += "_"; tableName += suffix; // debug msg - // std::cout << "\nSaving the published '"<< nodeType << "' nodes to the - // custom table: '" + // std::cout << "\nSaving the published '"<< nodeType << "' nodes to + // the custom table: '" // << tableName << "'." << std::endl; } // create custom table first then add to it createTableCustomPublishedNodes(tableName, nodeType, &keyType); return addListOfRecordsToTable(tableName, records); // needs SQLite >= 3.7.11 - // return addListOfRecordsToTableOld( tableName, records ); // old SQLite - // versions + // return addListOfRecordsToTableOld( tableName, records ); // old + // SQLite versions } bool GMDBManager::addListOfPublishedFullPhysVols( @@ -366,16 +373,16 @@ bool GMDBManager::addListOfPublishedFullPhysVols( if ("" != suffix) { tableName += "_"; tableName += suffix; - // std::cout << "\nSaving the published '"<< nodeType << "' nodes to the - // custom table: '" + // std::cout << "\nSaving the published '"<< nodeType << "' nodes to + // the custom table: '" // << tableName << "'." << std::endl; } // create custom table first then add to it createTableCustomPublishedNodes(tableName, nodeType, &keyType); return addListOfRecordsToTable(tableName, records); // needs SQLite >= 3.7.11 - // return addListOfRecordsToTableOld( tableName, records ); // old SQLite - // versions + // return addListOfRecordsToTableOld( tableName, records ); // old + // SQLite versions } /* @@ -383,8 +390,8 @@ bool GMDBManager::addListOfRecordsToCustomTable(const std::vector<std::vector<std::string>> &records, std::string tableName ) { std::string nodeType = "GeoFullPhysVol"; - const std::type_info &keyType(typeid(std::string));//TODO: type should be -custom too!! + const std::type_info &keyType(typeid(std::string));//TODO: type should +be custom too!! // create custom table first createTableCustomPublishedNodes( tableName, nodeType, &keyType ); // add records to the newly-created table @@ -398,7 +405,8 @@ versions bool GMDBManager::addListOfRecords( const std::string geoType, const std::vector<std::vector<std::string>> records) { - // if (m_debug) qDebug() << "GMDBManager::addListOfRecords():" << geoType; + // if (m_debug) qDebug() << "GMDBManager::addListOfRecords():" << + // geoType; std::string tableName = m_childType_tableName[geoType]; @@ -413,8 +421,8 @@ bool GMDBManager::addListOfRecords( // NOTE: Choose the right function!! return addListOfRecordsToTable( tableName, records); // better, but needs SQLite >= 3.7.11 - // return addListOfRecordsToTableOld(tableName, records); // old SQLite - // versions + // return addListOfRecordsToTableOld(tableName, records); // old + // SQLite versions } else { if (m_debug) std::cout << "Info: no records to save for geoType '" << geoType @@ -455,8 +463,8 @@ bool GMDBManager::addListOfRecordsToTable( items.push_back( "'" + item + "'"); // TODO: we should differentiate strings from other - // values when inserting them in the table, as we now do - // for the std::variant version! + // values when inserting them in the table, as we now + // do for the std::variant version! } std::string values = joinVectorStrings(items, ","); sql += " (" + std::to_string(id) + "," + values + ")"; @@ -518,9 +526,9 @@ bool GMDBManager::addListOfRecordsToTable( else if (std::holds_alternative<std::string>(item)) { std::string str = std::get<std::string>(item); // NOTE: if item is a "NULL" string, we don't encapsulate it - // into quotes, so it is taken as the SQL's NULL value in the - // SQL string, and inserted as a NULL value in the table, - // instead of as a "NULL" text string + // into quotes, so it is taken as the SQL's NULL value in + // the SQL string, and inserted as a NULL value in the + // table, instead of as a "NULL" text string if (str == "NULL") items.push_back(str); else @@ -547,10 +555,10 @@ bool GMDBManager::addListOfRecordsToTable( return true; } -// TODO: this is for the old SQLite. Not needed anymore, I guess. ==> Just put a -// requirement on the newer version of SQLite3 in CMakeLists.txt. Perhaps, also -// check that GeoModelIO can run smoothly on older ATLAS releases, like 21.9 by -// taking a newer SQLite3 from LCG. +// TODO: this is for the old SQLite. Not needed anymore, I guess. ==> Just +// put a requirement on the newer version of SQLite3 in CMakeLists.txt. +// Perhaps, also check that GeoModelIO can run smoothly on older ATLAS +// releases, like 21.9 by taking a newer SQLite3 from LCG. // ***Note*** // old syntax, for SQLite in SLC6 // here below we build the syntax for multiple INSERT @@ -558,8 +566,9 @@ bool GMDBManager::addListOfRecordsToTable( // see: stackoverflow.com/questions/1609637 // // we want to build a query like this: -// queryStr = QString("INSERT INTO Materials (id, name) SELECT 1 as id, 'Air' -// as name UNION ALL SELECT 2,'Silicon' UNION ALL SELECT 368,'ShieldSteel' ") +// queryStr = QString("INSERT INTO Materials (id, name) SELECT 1 as id, +// 'Air' as name UNION ALL SELECT 2,'Silicon' UNION ALL SELECT +// 368,'ShieldSteel' ") // /* bool GMDBManager::addListOfRecordsToTableOld(const QString tableName, const @@ -574,18 +583,19 @@ tableColString = "(" + QString::fromStdString(tabColNames) + ")"; QStringList colNames = m_tableNames.at(tableName); unsigned int nRecords = records.size(); - qInfo() << "number of " << tableName << "records to insert into the DB:" << -nRecords; + qInfo() << "number of " << tableName << "records to insert into the DB:" +<< nRecords; - // SQLite has a limit on 'union' items, set at 500. So we have to split the -items if we have more. + // SQLite has a limit on 'union' items, set at 500. So we have to split +the items if we have more. // See: stackoverflow.com/questions/9527851/ unsigned int bunchSize = 500; if ( nRecords > bunchSize ) { qWarning() << "WARNING! " << nRecords << " records of type " << -tableName << "to store in the DB in one call! Call limit is " << bunchSize << " +tableName << "to store in the DB in one call! Call limit is " << bunchSize +<< " --> We split them in bunches..."; std::vector<QStringList> recordsCopy( records ); // TODO: maybe we @@ -604,22 +614,22 @@ should use a deque or queue, which have fast pop of first element? queryStr = queryStr.arg(tableColString); // insert table columns first = recordsCopy.begin(); - last = recordsCopy.size() > bunchSize ? recordsCopy.begin() + bunchSize -: recordsCopy.end(); + last = recordsCopy.size() > bunchSize ? recordsCopy.begin() + +bunchSize : recordsCopy.end(); std::vector<QStringList> recordsBunch( first, last ); // we take the -first 500 records recordsCopy.erase( first, last ); // we delete the first 500 -records if (m_debug) qDebug() << "start:" << start << "recordsBunch size:" << -recordsBunch.size() << "- recordsCopy size after removal:" << +first 500 records recordsCopy.erase( first, last ); // we delete the first +500 records if (m_debug) qDebug() << "start:" << start << "recordsBunch +size:" << recordsBunch.size() << "- recordsCopy size after removal:" << recordsCopy.size(); // --- first record // outcome should be like: " 1 as id, 'Air' as name " unsigned int id = start+1; // set the first ID as 'start' - QStringList recFirst = recordsBunch.front(); // access first record from -vector recordsBunch.erase( recordsBunch.begin() ); // delete first record if -(m_debug) qDebug() << "after taking first record - recordsBunch size:" << -recordsBunch.size(); + QStringList recFirst = recordsBunch.front(); // access first record +from vector recordsBunch.erase( recordsBunch.begin() ); // delete first +record if (m_debug) qDebug() << "after taking first record - recordsBunch +size:" << recordsBunch.size(); // first item in the first record (it is the ID) QString firstCol = colNames[0]; @@ -645,9 +655,9 @@ recordsBunch.size(); // DEBUG if (tableName == -"Functions") { if (recs[1].length() > 65000) { std::cout << "LONG STRING! size: -" << recs[1].length() << std::endl; std::cout << "LONG STRING! string: " << -recs[1].toStdString() << std::endl << std::endl; +"Functions") { if (recs[1].length() > 65000) { std::cout << "LONG STRING! +size: " << recs[1].length() << std::endl; std::cout << "LONG STRING! string: +" << recs[1].toStdString() << std::endl << std::endl; } } //------ @@ -660,8 +670,8 @@ recs[1].toStdString() << std::endl << std::endl; } // join items into a string and add the SQL commands QString itemsStr = items.join(", "); - queryStr += " UNION ALL SELECT " + QString::number(id) + ", " + -itemsStr; + queryStr += " UNION ALL SELECT " + QString::number(id) + ", +" + itemsStr; } //qDebug() << "queryStr:" << queryStr; @@ -810,8 +820,8 @@ std::vector<std::string> GMDBManager::getItemAndType(unsigned int tableId, std::vector<std::string> GMDBManager::getItemFromTableName( std::string tableName, unsigned int id) { - // FIXME: when you create caches for all tables, replace this method with a - // lookup action in the cache. + // FIXME: when you create caches for all tables, replace this method + // with a lookup action in the cache. /* * Get the object from DB. */ @@ -842,9 +852,10 @@ std::vector<std::string> GMDBManager::getItemFromTableName( i++) // Loop times the number of columns in the table { std::string s = (char*)sqlite3_column_text( - stmt, i); // Read each Column in the row as text FIXME: - // is there a method to get the right type, - // e.g. double, instead of text? + stmt, + i); // Read each Column in the row as text FIXME: + // is there a method to get the right type, + // e.g. double, instead of text? item.push_back(s); } } @@ -951,8 +962,9 @@ int GMDBManager::loadGeoNodeTypesAndBuildCache() { return rc; } -// FIXME: should throw an error if the method `loadGeoNodeTypesAndBuildCache()` -// was not called before calling this method +// FIXME: should throw an error if the method +// `loadGeoNodeTypesAndBuildCache()` was not called before calling this +// method std::string GMDBManager::getTableNameFromTableId(unsigned int tabId) { return m_cache_tableId_tableName[tabId]; } @@ -997,6 +1009,18 @@ sqlite3_stmt* GMDBManager::Imp::selectAllFromTableSortBy( return st; } +bool GMDBManager::Imp::checkTable_imp(std::string tableName) const { + theManager->checkIsDBOpen(); + sqlite3_stmt* st = nullptr; // SQLite statement to be returned + int rc = -1; // SQLite return code + // set the SQL query string + std::string sql = fmt::format("SELECT * FROM {0}", tableName); + // prepare the query + rc = sqlite3_prepare_v2(m_dbSqlite, sql.c_str(), -1, &st, NULL); + if (rc != SQLITE_OK) return false; + return true; +} + sqlite3_stmt* GMDBManager::Imp::selectAllFromTableChildrenPositions() const { theManager->checkIsDBOpen(); sqlite3_stmt* st = nullptr; @@ -1035,7 +1059,8 @@ void GMDBManager::getAllDBTables() { std::vector<std::string> tables; // define a query string containing the necessary SQL instructions std::string queryStr = - "SELECT name FROM sqlite_master WHERE type ='table' AND name NOT LIKE " + "SELECT name FROM sqlite_master WHERE type ='table' AND name NOT " + "LIKE " "'sqlite_%';"; // prepare the query with the query string sqlite3_stmt* stmt; @@ -1068,7 +1093,9 @@ void GMDBManager::getAllDBTableColumns() { // populate the cache with tables' names, if needed if (!m_cache_tables.size()) { - std::cout << "*** ERROR! Tables' cache is empty! ***\n"; + if (m_debug) { + std::cout << "*** WARNING! Tables' cache is empty! That's normal if you are saving a GeoModel tree into a new .db file. ***\n"; + } return; } @@ -1082,15 +1109,15 @@ void GMDBManager::getAllDBTableColumns() { &stmt, NULL); if (rc == SQLITE_OK) { // OK, now looping over table's columns... - // will continue to go down the rows (columns in your table) till - // there are no more + // will continue to go down the rows (columns in your table) + // till there are no more while (sqlite3_step(stmt) == SQLITE_ROW) { // sprintf(colName, "%s", sqlite3_column_text(stmt, 1)); colName = std::string(reinterpret_cast<const char*>( sqlite3_column_text(stmt, 0))); - // do something with colName because it contains the column's - // name + // do something with colName because it contains the + // column's name m_tableNames[tableName].push_back(colName); } } @@ -1123,6 +1150,10 @@ std::vector<std::vector<std::string>> GMDBManager::getPublishedAXFTable( return getTableRecords(tableName); } +bool GMDBManager::checkTable(std::string tableName) const { + return m_d->checkTable_imp(tableName); +} + // create a user-defined custom table to store the published nodes // (usually GeoFullPhysVol and AlignableTransform nodes) and their keys. bool GMDBManager::createTableCustomPublishedNodes( @@ -1189,10 +1220,10 @@ std::vector<std::string> tableColTypes, const std::vector<std::vector<std::string>> &records ) { if( tableColNames.size() == 0 ) throw -std::runtime_error("GMDBManager::createCustomTable -- The list of columns' names -is empty!!"); if( tableColTypes.size() == 0 ) throw -std::runtime_error("GMDBManager::createCustomTable -- The list of columns' types -is empty!!"); +std::runtime_error("GMDBManager::createCustomTable -- The list of columns' +names is empty!!"); if( tableColTypes.size() == 0 ) throw +std::runtime_error("GMDBManager::createCustomTable -- The list of columns' +types is empty!!"); int rc = -1; // sqlite's return code std::string queryStr; @@ -1207,10 +1238,11 @@ is empty!!"); storeTableColumnNames(tab); // prepare the dynamic query to create the custom table - queryStr = fmt::format( "create table {0} ( id integer primary key ", tab[0] + queryStr = fmt::format( "create table {0} ( id integer primary key ", +tab[0] ); for( int ii=0; ii<tableColNames.size(); ++ii) { std::string colStr = -fmt::format( ", {0} {1} ", tableColNames[ii], tableColTypes[ii] ); queryStr += -colStr; +fmt::format( ", {0} {1} ", tableColNames[ii], tableColTypes[ii] ); queryStr ++= colStr; } queryStr += ")"; @@ -1231,11 +1263,13 @@ bool GMDBManager::createCustomTable( records) { if (tableColNames.size() == 0) throw std::runtime_error( - "GMDBManager::createCustomTable -- The list of columns' names is " + "GMDBManager::createCustomTable -- The list of columns' names " + "is " "empty!!"); if (tableColTypes.size() == 0) throw std::runtime_error( - "GMDBManager::createCustomTable -- The list of columns' types is " + "GMDBManager::createCustomTable -- The list of columns' types " + "is " "empty!!"); std::string queryStr; @@ -1254,22 +1288,23 @@ bool GMDBManager::createCustomTable( for (size_t ii = 0; ii < tableColNames.size(); ++ii) { std::string colType = ""; - // -- Here we check the datum's type, which is more universal than using - // string-encoded types + // -- Here we check the datum's type, which is more universal than + // using string-encoded types // -- but this does not work if the first entry of a given column is // empty. - // -- If so, the 'null' entry is taken as string, and the column is set - // as containing TEXT... convert std::variant types to SQLite data types - // (see SQLite documentation) + // -- If so, the 'null' entry is taken as string, and the column is + // set as containing TEXT... convert std::variant types to SQLite + // data types (see SQLite documentation) /* - if( std::holds_alternative<int>(records[0][ii]) ) colType = + if( std::holds_alternative<int>(records[0][ii]) ) colType = "INTEGER"; else if( std::holds_alternative<long>(records[0][ii]) ) colType = "INTEGER"; else if( - std::holds_alternative<float>(records[0][ii]) ) colType = "REAL"; - else if( std::holds_alternative<double>(records[0][ii]) ) colType = - "REAL"; else if( std::holds_alternative<std::string>(records[0][ii]) ) - colType = "TEXT"; else throw std::runtime_error("No std::variant - alternative has been found!\n"); + std::holds_alternative<float>(records[0][ii]) ) colType = + "REAL"; else if( std::holds_alternative<double>(records[0][ii]) ) + colType = "REAL"; else if( + std::holds_alternative<std::string>(records[0][ii]) ) colType = + "TEXT"; else throw std::runtime_error("No std::variant alternative + has been found!\n"); */ if (tableColTypes[ii] == "INT") @@ -1311,8 +1346,8 @@ bool GMDBManager::createTables() { std::string tableName; std::vector<std::string> tab; - // create a table to store the relation between the types of GeoNodes and - // the name of the table + // create a table to store the relation between the types of GeoNodes + // and the name of the table tableName = "dbversion"; tab.insert(tab.begin(), {tableName, "id", "version"}); storeTableColumnNames(tab); @@ -1322,19 +1357,21 @@ bool GMDBManager::createTables() { rc = execQuery(queryStr); tab.clear(); - // create a table to store the relation between the types of GeoNodes and - // the name of the table + // create a table to store the relation between the types of GeoNodes + // and the name of the table tableName = "GeoNodesTypes"; tab.insert(tab.begin(), {tableName, "id", "nodeType", "tableName"}); storeTableColumnNames(tab); queryStr = fmt::format( - "create table {0}({1} integer primary key, {2} varchar, {3} varchar)", + "create table {0}({1} integer primary key, {2} varchar, {3} " + "varchar)", tab[0], tab[1], tab[2], tab[3]); rc = execQuery(queryStr); tab.clear(); - // create a table to store the mother-daughter relationships between nodes - // (notably, between the [Full]PhysVols as the parents and their children) + // create a table to store the mother-daughter relationships between + // nodes (notably, between the [Full]PhysVols as the parents and their + // children) tableName = "ChildrenPositions"; tab.push_back(tableName); tab.push_back("id"); @@ -1347,16 +1384,19 @@ bool GMDBManager::createTables() { tab.push_back("childCopyNumber"); storeTableColumnNames(tab); queryStr = fmt::format( - "create table {0}({1} integer primary key, {2} integer, {3} integer " - "not null REFERENCES GeoNodesTypes(id), {4} integer, {5} integer, {6} " - "integer not null REFERENCES GeoNodesTypes(id), {7} integer not null, " + "create table {0}({1} integer primary key, {2} integer, {3} " + "integer " + "not null REFERENCES GeoNodesTypes(id), {4} integer, {5} integer, " + "{6} " + "integer not null REFERENCES GeoNodesTypes(id), {7} integer not " + "null, " "{8} integer not null)", tab[0], tab[1], tab[2], tab[3], tab[4], tab[5], tab[6], tab[7], tab[8]); rc = execQuery(queryStr); tab.clear(); - // create a table to store information about the 'root' volume (also known - // as the 'world' volume) + // create a table to store information about the 'root' volume (also + // known as the 'world' volume) tableName = "RootVolume"; tab.push_back(tableName); tab.push_back("id"); @@ -1364,7 +1404,8 @@ bool GMDBManager::createTables() { tab.push_back("volTable"); storeTableColumnNames(tab); queryStr = fmt::format( - "create table {0}({1} integer primary key, {2} integer not null, {3} " + "create table {0}({1} integer primary key, {2} integer not null, " + "{3} " "integer not null REFERENCES GeoNodesTypes(id))", tab[0], tab[1], tab[2], tab[3]); rc = execQuery(queryStr); @@ -1413,7 +1454,8 @@ bool GMDBManager::createTables() { tab.push_back("material"); storeTableColumnNames(tab); queryStr = fmt::format( - "create table {0}({1} integer primary key, {2} varchar, {3} integer " + "create table {0}({1} integer primary key, {2} varchar, {3} " + "integer " "not null, {4} integer not null)", tab[0], tab[1], tab[2], tab[3], tab[4]); if (0 == (rc = execQuery(queryStr))) { @@ -1432,7 +1474,8 @@ bool GMDBManager::createTables() { tab.push_back("elements"); storeTableColumnNames(tab); queryStr = fmt::format( - "create table {0}({1} integer primary key, {2} varchar, {3} varchar, " + "create table {0}({1} integer primary key, {2} varchar, {3} " + "varchar, " "{4} varchar)", tab[0], tab[1], tab[2], tab[3], tab[4]); if (0 == (rc = execQuery(queryStr))) { @@ -1452,7 +1495,8 @@ bool GMDBManager::createTables() { tab.push_back("A"); storeTableColumnNames(tab); queryStr = fmt::format( - "create table {0}({1} integer primary key, {2} varchar, {3} varchar, " + "create table {0}({1} integer primary key, {2} varchar, {3} " + "varchar, " "{4} varchar, {5} varchar)", tab[0], tab[1], tab[2], tab[3], tab[4], tab[5]); if (0 == (rc = execQuery(queryStr))) { @@ -1470,7 +1514,8 @@ bool GMDBManager::createTables() { tab.push_back("parameters"); storeTableColumnNames(tab); queryStr = fmt::format( - "create table {0}({1} integer primary key, {2} varchar, {3} varchar)", + "create table {0}({1} integer primary key, {2} varchar, {3} " + "varchar)", tab[0], tab[1], tab[2], tab[3]); if (0 == (rc = execQuery(queryStr))) { storeNodeType(geoNode, tableName); @@ -1554,7 +1599,8 @@ bool GMDBManager::createTables() { storeTableColumnNames(tab); queryStr = fmt::format( "create table {0}({1} integer primary key, {2} integer not null " - "REFERENCES Functions(id), {3} integer not null, {4} integer not null " + "REFERENCES Functions(id), {3} integer not null, {4} integer not " + "null " "REFERENCES GeoNodesTypes(id), {5} integer)", tab[0], tab[1], tab[2], tab[3], tab[4], tab[5]); if (0 == (rc = execQuery(queryStr))) { @@ -1583,7 +1629,8 @@ bool GMDBManager::createTables() { storeTableColumnNames(tab); queryStr = fmt::format( "create table {0}({1} integer primary key, {2} real, {3} real, {4} " - "real, {5} real, {6} real, {7} real, {8} real, {9} real, {10} real, " + "real, {5} real, {6} real, {7} real, {8} real, {9} real, {10} " + "real, " "{11} real, {12} real, {13} real)", tab[0], tab[1], tab[2], tab[3], tab[4], tab[5], tab[6], tab[7], tab[8], tab[9], tab[10], tab[11], tab[12], tab[13]); @@ -1613,7 +1660,8 @@ bool GMDBManager::createTables() { storeTableColumnNames(tab); queryStr = fmt::format( "create table {0}({1} integer primary key, {2} real, {3} real, {4} " - "real, {5} real, {6} real, {7} real, {8} real, {9} real, {10} real, " + "real, {5} real, {6} real, {7} real, {8} real, {9} real, {10} " + "real, " "{11} real, {12} real, {13} real)", tab[0], tab[1], tab[2], tab[3], tab[4], tab[5], tab[6], tab[7], tab[8], tab[9], tab[10], tab[11], tab[12], tab[13]); @@ -1722,7 +1770,8 @@ void GMDBManager::storeNodeType(std::string nodeType, std::string tableName) { // QSqlQuery q; // // // // qDebug() << "Loading Shapes..."; -// // if (!q.prepare(QLatin1String("insert into Shapes(name) values(?)"))) { +// // if (!q.prepare(QLatin1String("insert into Shapes(name) values(?)"))) +// { // // showError(q.lastError()); // // return; // // } @@ -1739,8 +1788,9 @@ void GMDBManager::storeNodeType(std::string nodeType, std::string tableName) { // QVariant leadId = // addMaterial(QLatin1String("Lead"),QLatin1String("density"),QLatin1String("elements")); // -// QVariant worldLogId = addLogVol(QLatin1String("WorldLog"), boxId, airId); -// QVariant toyLogId = addLogVol(QLatin1String("ToyLog"), coneId, leadId); +// QVariant worldLogId = addLogVol(QLatin1String("WorldLog"), boxId, +// airId); QVariant toyLogId = addLogVol(QLatin1String("ToyLog"), coneId, +// leadId); // // QVariant rootPhysId = addPhysVol(worldLogId, QVariant()); // no parent // QVariant childPhysId = addPhysVol(toyLogId, rootPhysId); @@ -1799,8 +1849,8 @@ std::vector<std::string> GMDBManager::getRootPhysVol() { int rc = -1; while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) { // get the data - id = sqlite3_column_int(stmt, 0); - typeId = sqlite3_column_int(stmt, 1); + id = sqlite3_column_int(stmt, 1); + typeId = sqlite3_column_int(stmt, 2); // TODO: fill a cache } if (rc != SQLITE_DONE) { @@ -1810,8 +1860,10 @@ std::vector<std::string> GMDBManager::getRootPhysVol() { } // finalize sqlite3_finalize(stmt); - - return getItemAndType(typeId, id); + + std::vector<std::string> results = getItemAndType(typeId, id); + return results; + } std::string GMDBManager::getDBFilePath() { return m_dbpath; } diff --git a/GeoModelIO/GeoModelDBManager/tests/test_create_db_file.cpp b/GeoModelIO/GeoModelDBManager/tests/test_create_db_file.cpp new file mode 100644 index 0000000000000000000000000000000000000000..970e18de7a8f9a009549d12bfb04cd3b692517be --- /dev/null +++ b/GeoModelIO/GeoModelDBManager/tests/test_create_db_file.cpp @@ -0,0 +1,53 @@ +// Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration + +/* + * this test simply creates a GeoModel .db file + * through the use of GeoModelDBManager, + * then it deletes it. + * + * author: Riccardo Maria BIANCHI <riccardo.maria.bianchi@cern.ch> + * 2023, Dec 11 + * + */ + + +// GeoModel includes +#include "GeoModelDBManager/GMDBManager.h" +// c++ includes +#include <fstream> + + +int main(int argc, char *argv[]) +{ + //------------------------------------------------------------------------------------// + // Open a geometry file + //------------------------------------------------------------------------------------// + std::string path = "geometry.db"; + + // check if DB file exists. If not, return. + // FIXME: TODO: this check should go in the 'GMDBManager' constructor. + std::ifstream infile(path.c_str()); + if ( infile.good() ) { + std::cout << "\n\tERROR!! A '" << path << "' file exists already!! Please, remove, move, or rename it before running this program. Exiting..."; + exit(EXIT_FAILURE); + } + infile.close(); + + // open the DB connection + GMDBManager db(path); + + // check the DB connection + if (db.checkIsDBOpen()) { + std::cout << "OK! Database is open!" << std::endl; + } else { + std::cout << "Database ERROR!! Exiting..." << std::endl; + exit(EXIT_FAILURE); + } + + std::cout << "Now, we remove the test .db file...\n"; + std::remove(path.c_str()); // delete file + std::cout << "OK, test .db file removed.\n"; + + + return 0; +} diff --git a/GeoModelIO/GeoModelIOHelpers/CMakeLists.txt b/GeoModelIO/GeoModelIOHelpers/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..ca1bb3fcdabfa7b74c5501ed49682d2a25e8f24d --- /dev/null +++ b/GeoModelIO/GeoModelIOHelpers/CMakeLists.txt @@ -0,0 +1,48 @@ +# Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration +################################################################################ +# Package: GeoModelIOHelpers +# author: Riccardo Maria BIANCHI <rbianchi@cern.ch> - 2023 Jan +################################################################################ + +# Find the header and source files. +file( GLOB SOURCES src/*.cpp ) +file( GLOB HEADERS GeoModelIOHelpers/*.h ) + +# Set up the library. +add_library( GeoModelIOHelpers SHARED ${HEADERS} ${SOURCES} ) +target_link_libraries( GeoModelIOHelpers PUBLIC + GeoModelRead GeoModelWrite ) +# We link those to carry on the needed libs when including GeoModelIOHelpers, +# even if the latter is headers only +target_include_directories( GeoModelIOHelpers PUBLIC + $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> + $<INSTALL_INTERFACE:include> ) +source_group( "GeoModelIOHelpers" FILES ${HEADERS} ) +source_group( "src" FILES ${SOURCES} ) +set_target_properties( GeoModelIOHelpers PROPERTIES + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR} ) +set_target_properties(GeoModelIOHelpers PROPERTIES LINKER_LANGUAGE CXX) + +# Set up custom build flags for the library. +foreach( _flag GEOMODEL_IO_READ_DEBUG GEOMODEL_IO_DEBUG_VERBOSE + GEOMODEL_IO_READ_TIMING ) + if( ${${_flag}} ) + target_compile_definitions( GeoModelIOHelpers PRIVATE ${_flag}=true ) + endif() +endforeach() + +# Set up an alias with the same name that you would get by "finding" a pre-built +# version of the library. +add_library( GeoModelIO::GeoModelIOHelpers ALIAS GeoModelIOHelpers ) + +# Install the library. +install(TARGETS GeoModelIOHelpers + EXPORT ${PROJECT_NAME}-export + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT Runtime + NAMELINK_COMPONENT Development # Requires CMake 3.12 +) +install( FILES ${HEADERS} + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/GeoModelIOHelpers + COMPONENT Development ) diff --git a/GeoModelIO/GeoModelIOHelpers/GeoModelIOHelpers/GMIO.h b/GeoModelIO/GeoModelIOHelpers/GeoModelIOHelpers/GMIO.h new file mode 100644 index 0000000000000000000000000000000000000000..0e4b211b5bd7cdbbd62c033f1f18beb92a637e8b --- /dev/null +++ b/GeoModelIO/GeoModelIOHelpers/GeoModelIOHelpers/GMIO.h @@ -0,0 +1,317 @@ + +// Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration + +/* + * This header file provides helper functions to write and read a GeoModel SQLite file. + * + * Author: Riccardo Maria BIANCHI @ CERN + * Created on: Feb, 2023 + * + */ + + +#ifndef GMIO_H +#define GMIO_H + +// C++ includes +#include <cstdlib> // EXIT_FAILURE +#include <fstream> +#include <string> + +#include "GeoModelDBManager/GMDBManager.h" +#include "GeoModelRead/ReadGeoModel.h" +#include "GeoModelWrite/WriteGeoModel.h" + +namespace GeoModelIO { + +class IO { + public: + + // dummy constructor + IO(){}; + + static GMDBManager saveToDB(const GeoVPhysVol* world, const std::string path, + unsigned loglevel = 0, const bool forceDelete = false ) { + // Check if the output DB file exists already. + // - If yes and the 'forceDelete' option is set to 'true' by the user, + // then delete it before trying to create the new one; that is, + // the 'forceDelete' option replaces the existing '.db' file. + // - If yes and the 'forceDelete' option is set to 'false', then throw + // and error and exits. + std::ifstream inputfile(path.c_str()); + if (inputfile.good()) { + if (true == forceDelete) { + std::cout << "GeoModelIO -- INFO: you set the 'forceDelete' option to 'true', so we replace the existing .db file: '" << path << "'." << std::endl; + std::remove(path.c_str()); // delete file + } else { + std::cerr << "\n*** ERROR! The output '" << path << "' file exists already! If you want to replace it, set the 'forceDelete' option to 'true'. Otherwise, rename the existing file, or move it to another place, and retry. ***\n\n{" + << __func__ << " [" + << __PRETTY_FUNCTION__ + << "]}\n\n"; + throw; + } + } + inputfile.close(); + + // open the DB connection + GMDBManager db(path); + + // check the DB connection + if (!db.checkIsDBOpen()) { + std::cout << "Database ERROR!! Exiting..." << std::endl; + exit(EXIT_FAILURE); + } + + // Dump the tree volumes to a local file + std::cout << "Dumping the GeoModel geometry to the DB file..." + << std::endl; + // init the GeoModel node action + GeoModelIO::WriteGeoModel dumpGeoModelGraph(db); + // set loglevel of write action, if > 0 + if (loglevel > 0) { + dumpGeoModelGraph.setLogLevel(loglevel); + } + world->exec(&dumpGeoModelGraph); // visit all GeoModel nodes + dumpGeoModelGraph.saveToDB(); // save to the SQlite DB file + std::cout << "DONE. Geometry saved." << std::endl; + return db; + } + + static const GeoVPhysVol* loadDB(const std::string path, unsigned loglevel = 0) { + // check if DB file exists. + // If not, print a warning message and return a nullptr. + std::ifstream inputfile(path.c_str()); + bool failed = false; + if (!inputfile.good()) { + std::cerr << "\n*** WARNING! The input .db file does not exist! Check the path of the input file. Returning a nullptr... ***\n{" + << __func__ << " [" + << __PRETTY_FUNCTION__ + << "]}\n\n"; + failed = true; + } + inputfile.close(); + if(failed) { + return nullptr; + } + + // open the DB + GMDBManager* db = new GMDBManager(path); + if (!db->checkIsDBOpen()) { + std::cout << "ERROR!! -- Database is not open!\n"; + throw; + } + + /* setup the GeoModel reader */ + GeoModelIO::ReadGeoModel geoReader = GeoModelIO::ReadGeoModel(db); + // set loglevel of read action, if > 0 + if (loglevel > 0) { + geoReader.setLogLevel(loglevel); + } + + /* build the GeoModel geometry */ + // builds the whole GeoModel tree in memory + const GeoVPhysVol* rootVolume = geoReader.buildGeoModel(); + + delete db; + db = nullptr; + + return rootVolume; // FIXME: See if you can pass a smart ptr + } + + static GeoModelIO::ReadGeoModel getReaderDB(const std::string path, unsigned loglevel = 0) { + // check if DB file exists. + // If not, print a warning message and exit. + std::ifstream inputfile(path.c_str()); + if (!inputfile.good()) { + std::cerr << "\n*** ERROR! The input .db file does not exist! Check the path of the input file. Exiting...\n" + << "{ " << __func__ << " " + << "[" << __PRETTY_FUNCTION__ + << "]}.\n\n"; + exit(EXIT_FAILURE); + } + inputfile.close(); + + // open the DB + GMDBManager* db = new GMDBManager(path); + if (!db->checkIsDBOpen()) { + std::cout << "ERROR!! -- Database is not open!\n"; + throw; + } + + /* setup the GeoModel reader */ + GeoModelIO::ReadGeoModel geoReader = GeoModelIO::ReadGeoModel(db); + // set loglevel of read action, if > 0 + if (loglevel > 0) { + geoReader.setLogLevel(loglevel); + } + + return geoReader; // FIXME: See if you can pass a smart ptr + } + + static std::map<std::string, unsigned long> countNodesFromDB( + GMDBManager& db) { + // map to populate and return + std::map<std::string, unsigned long> mmap; + // get the number of all nodes in the DB from the DB manager + unsigned long nphysvols = db.getTableFromNodeType("GeoPhysVol").size(); + unsigned long nfullphysvols = + db.getTableFromNodeType("GeoFullPhysVol").size(); + unsigned long nlogvols = db.getTableFromNodeType("GeoLogVol").size(); + unsigned long nelements = db.getTableFromNodeType("GeoElement").size(); + unsigned long nmaterials = + db.getTableFromNodeType("GeoMaterial").size(); + unsigned long nalignables = + db.getTableFromNodeType("GeoAlignableTransform").size(); + unsigned long nfunctions = db.getTableFromNodeType("Function").size(); + unsigned long nserialtransformers = + db.getTableFromNodeType("GeoSerialTransformer").size(); + unsigned long nshapes = db.getTableFromNodeType("GeoShape").size(); + unsigned long nserialdenominators = + db.getTableFromNodeType("GeoSerialDenominator").size(); + // get metadata + unsigned long nchildrenconnections = db.getChildrenTable().size(); + + return mmap; + } + + static std::map<std::string, unsigned long> countTreeMemoryNodesFromVolume( + const GeoVPhysVol* world, unsigned loglevel = 0) { + std::map<std::string, unsigned long> mmap; + + // init the graph action to count all nodes in the in-memory tree + GeoModelIO::WriteGeoModel dump; + // set loglevel of write action, if > 0 + if (loglevel > 0) { + dump.setLogLevel(loglevel); + } + world->exec(&dump); // visit all GeoModel nodes + + unsigned long nphysvols = dump.getNPhysVols(); + unsigned long nfullphysvols = dump.getNFullPhysVols(); + unsigned long nlogvols = dump.getNLogVols(); + unsigned long nelements = dump.getNElements(); + unsigned long nmaterials = dump.getNMaterials(); + unsigned long nalignables = dump.getNAlignableTransforms(); + unsigned long nfunctions = dump.getNFunctions(); + unsigned long nserialtransformers = dump.getNSerialTransformers(); + unsigned long nshapes = dump.getNShapes(); + unsigned long nserialdenominators = dump.getNSerialDenominators(); + unsigned long nchildrenconnections = dump.getNChildrenConnections(); + // unsigned nrootvolume = dump.getNRootVolume(); + unsigned long ntransforms = dump.getNTransforms(); + unsigned long nserialidentifiers = dump.getNSerialIdentifiers(); + unsigned long nidentifiertags = dump.getNIdentifierTags(); + unsigned long nnametags = dump.getNNameTags(); + + mmap["PhysVol"] = nphysvols; + mmap["FullPhysVol"] = nfullphysvols; + mmap["LogVol"] = nlogvols; + mmap["Element"] = nelements; + mmap["Material"] = nmaterials; + mmap["Alignable"] = nalignables; + mmap["Function"] = nfunctions; + mmap["SerialTransformer"] = nserialtransformers; + mmap["Shape"] = nshapes; + mmap["SerialDenominator"] = nserialdenominators; + mmap["ChildrenConnections"] = nchildrenconnections; + mmap["Transform"] = ntransforms; + mmap["SerialIdentifier"] = nserialidentifiers; + mmap["IdentifierTag"] = nidentifiertags; + mmap["NameTag"] = nnametags; + + return mmap; + } + static std::map<std::string, unsigned long> countLoadedNodesFromReadAction( + GeoModelIO::ReadGeoModel& read) { + std::map<std::string, unsigned long> mmap; + + unsigned long nphysvols = read.getNPhysVols(); + unsigned long nfullphysvols = read.getNFullPhysVols(); + unsigned long nlogvols = read.getNLogVols(); + unsigned long nelements = read.getNElements(); + unsigned long nmaterials = read.getNMaterials(); + unsigned long nalignables = read.getNAlignableTransforms(); + unsigned long nfunctions = read.getNFunctions(); + unsigned long nserialtransformers = read.getNSerialTransformers(); + unsigned long nshapes = read.getNShapes(); + unsigned long nserialdenominators = read.getNSerialDenominators(); + unsigned long nchildrenconnections = read.getNChildrenConnections(); + // unsigned nrootvolume = read.getNRootVolume(); + unsigned long ntransforms = read.getNTransforms(); + unsigned long nserialidentifiers = read.getNSerialIdentifiers(); + unsigned long nidentifiertags = read.getNIdentifierTags(); + unsigned long nnametags = read.getNNameTags(); + + mmap["PhysVol"] = nphysvols; + mmap["FullPhysVol"] = nfullphysvols; + mmap["LogVol"] = nlogvols; + mmap["Element"] = nelements; + mmap["Material"] = nmaterials; + mmap["Alignable"] = nalignables; + mmap["Function"] = nfunctions; + mmap["SerialTransformer"] = nserialtransformers; + mmap["Shape"] = nshapes; + mmap["SerialDenominator"] = nserialdenominators; + mmap["ChildrenConnections"] = nchildrenconnections; + mmap["Transform"] = ntransforms; + mmap["SerialIdentifier"] = nserialidentifiers; + mmap["IdentifierTag"] = nidentifiertags; + mmap["NameTag"] = nnametags; + + return mmap; + } + + static void printNodesMap(std::map<std::string, unsigned long> mmap) { + for (auto& node : mmap) { + std::cout << node.first << ": " << node.second << std::endl; + } + } + + static void printKeyMaps(std::string key, + std::map<std::string, unsigned long> m1, + std::map<std::string, unsigned long> m2) { + std::cout << "number of " << key << " : " << m1[key] << " -- " + << m2[key] << std::endl; + } + + static std::vector<std::string> getMapKeys() { + std::vector<std::string> keys{"PhysVol", + "FullPhysVol", + "LogVol", + "Element", + "Material", + "Alignable", + "Function", + "SerialTransformer", + "Shape", + "Transform", + "SerialIdentifier", + "IdentifierTag", + "NameTag" + "SerialDenominator", + "ChildrenConnections"}; + return keys; + } + static void printCompareTwoNodesMaps( + std::map<std::string, unsigned long> m1, + std::map<std::string, unsigned long> m2) { + std::vector<std::string> keys = getMapKeys(); + for (auto& key : keys) { + printKeyMaps(key, m1, m2); + } + } + + static std::map<std::string, unsigned long> initNodesMap() { + std::map<std::string, unsigned long> nmap; + std::vector<std::string> keys = getMapKeys(); + // init the map + for (auto& key : keys) { + nmap[key] = 0; + } + return nmap; + } +}; + +} // namespace GeoModelIO + +#endif diff --git a/GeoModelIO/GeoModelIOHelpers/GeoModelIOHelpers/GMTests_IO.h b/GeoModelIO/GeoModelIOHelpers/GeoModelIOHelpers/GMTests_IO.h new file mode 100644 index 0000000000000000000000000000000000000000..a6f3f0e901fd931b591b4447ec63f7c56ee10feb --- /dev/null +++ b/GeoModelIO/GeoModelIOHelpers/GeoModelIOHelpers/GMTests_IO.h @@ -0,0 +1,287 @@ +// Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration + +/* + * This header file provides helper functions to perform different tests on an existing GeoModel tree. + * + * Author: Riccardo Maria BIANCHI @ CERN + * Created on: Feb, 2023 + * + */ + +#ifndef GMTESTS_IO_H +#define GMTESTS_IO_H + +#include "GeoModelDBManager/GMDBManager.h" +#include "GeoModelRead/ReadGeoModel.h" +#include "GeoModelIOHelpers/GMIO.h" + +namespace GeoModelIO { + +class TestIO { + public: + TestIO(){}; + + /// This function tests the number of nodes in the workflow + /// Write-Read-Write. In this test, a GeoVPhysVol is taken as a 'world' + /// volume and the GeoModel tree is persistified into a DB file. Then the + /// file is loaded and the GeoModel tree restored. Then the in-memory + /// GeoModel tree is persistified again into a new DB file. + /// This tests the IO tools that dump the in-memory GeoModel tree to file, + /// the ones that restore it from the DB file into memory, and the DB I/O + /// methods. + /// The number of nodes are taken from the DB, by using the tools offered by + /// the DB Manager. + static std::pair<std::string, bool> test_compareWriteReadWriteFromVol( + const GeoVPhysVol* world, const unsigned loglevel = 0, const bool forceDelete = false) { + std::string testname = "compareWriteReadWriteFromVol"; + if (loglevel >= 1) { + std::cout << "\n-- Test: '" << testname << "' -- \n"; + } + // test DBs + const std::string db1_name = "geometry_db_test_1.db"; + const std::string db2_name = "geometry_db_test_2.db"; + + //-----------------------------------------------// + // 1 -- Writing the geometry to file - 1st time + //-----------------------------------------------// + GMDBManager db1 = GeoModelIO::IO::saveToDB(world, db1_name, loglevel, forceDelete); + + //-----------------------------------------------// + // 2 -- Get number of nodes from the DB we just saved + //-----------------------------------------------// + std::map<std::string, unsigned long> mmap_1 = + GeoModelIO::IO::countNodesFromDB(db1); + + //-----------------------------------------------// + // 3 -- Reading back the geometry from file + //-----------------------------------------------// + const GeoVPhysVol* world2 = GeoModelIO::IO::loadDB(db1_name, loglevel); + + //-----------------------------------------------// + // 4 -- Writing the geometry to file - 2nd time + //-----------------------------------------------// + GMDBManager db2 = GeoModelIO::IO::saveToDB(world2, db2_name, loglevel, forceDelete); + + //-----------------------------------------------// + // 5 -- Get number of nodes from the DB we created from the restored + // GeoModel tree + //-----------------------------------------------// + std::map<std::string, unsigned long> mmap_2 = + GeoModelIO::IO::countNodesFromDB(db2); + + //-----------------------------------------------// + // 6 -- Comparison + //-----------------------------------------------// + + bool testok = false; + if (mmap_1 == mmap_2) { + if (loglevel >= 1) { + std::cout + << "OK! The number of nodes that were persistified is " + "equal to the " + "number of restored-then-persistified-again " + "(Write-Read-Write) nodes.\n"; + std::cout << "----\n"; + } + testok = true; + } else { + if (loglevel >= 1) { + std::cout << "!!! ERROR !!! The number of nodes that were " + "persistified is " + "NOT equal to the " + "number of restored-then-persistified-again " + "(Write-Read-Write) nodes!!!\n"; + if (loglevel >= 2) { + GeoModelIO::IO::printCompareTwoNodesMaps(mmap_1, mmap_2); + } + std::cout << "----\n"; + } + testok = false; + } + std::pair<std::string, bool> testout{testname, testok}; + return testout; + } + + /// This functions compares the number of nodes of the in-memory GeoModel + /// tree to the number of the saved-then-restored nodes. The number of nodes + /// are taken from the cache of the GeoNodeAction that is used to traverse + /// the GeoModel tree during the I/O operation, instead of being taken from + /// the DB. + static std::pair<std::string, bool> test_compareMemoryVsRestoredFromVol( + const GeoVPhysVol* world, const unsigned loglevel = 0, const bool forceDelete = false) { + std::string testname = "compareMemoryVsRestoredFromVol"; + if (loglevel >= 1) { + std::cout << "\n-- Test: '" << testname << "' -- \n"; + std::cout + << "1 -- Objects in the starting in-memory 'world' volume..." + << std::endl; + } + // printCountWorldMemoryObjects(world); + std::map<std::string, unsigned long> mmap_1 = + GeoModelIO::IO::countTreeMemoryNodesFromVolume(world); + if (loglevel >= 1) { + std::cout << "2 -- Saving the in-memory 'world' volume into a .db " + "file and " + "restoring the GeoModel tree from it..." + << std::endl; + } + std::string dbname = "test_geometry_db_memory.db"; + GMDBManager db = GeoModelIO::IO::saveToDB(world, dbname, loglevel, forceDelete); + const GeoVPhysVol* world2 = GeoModelIO::IO::loadDB(dbname, loglevel); + if (loglevel >= 1) { + std::cout + << "3 -- Objects in the restored in-memory 'world' volume..." + << std::endl; + } + // printCountWorldMemoryObjects(world2); + std::map<std::string, unsigned long> mmap_2 = + GeoModelIO::IO::countTreeMemoryNodesFromVolume(world2); + // TODO: remove temporary .db files when not needed anymore + // TODO: add number-by-number comparison as with the other tests!! + + bool testok = false; + if (mmap_1 == mmap_2) { + if (loglevel >= 1) { + std::cout << "OK! The number of starting in-memory nodes is " + "equal to the " + "number of the restored in-memory nodes.\n"; + std::cout << "----\n"; + } + testok = true; + } else { + if (loglevel >= 1) { + std::cout + << "!!! ERROR !!! The number of teh starting in-memory " + "nodes is DIFFERENT from " + "the number of the restored in-memory nodes!!!\n"; + if (loglevel >= 2) { + std::cout << "Starting in-memory nodes:\n"; + GeoModelIO::IO::printNodesMap(mmap_1); + std::cout << "Restored in-memory nodes:\n"; + GeoModelIO::IO::printNodesMap(mmap_2); + } + std::cout << "----\n"; + } + testok = false; + } + std::pair<std::string, bool> testout{testname, testok}; + return testout; + } + + /// Utility function to print the number of nodes of a GeoModel tree, + /// starting from a GeoVPhysVol taken as a 'world' volume. + static void printCountWorldMemoryObjects(const GeoVPhysVol* world) { + std::map<std::string, unsigned long> mmap = + GeoModelIO::IO::countTreeMemoryNodesFromVolume(world); + for (auto& node : mmap) { + std::cout << node.first << ": " << node.second << std::endl; + } + } + + /// This function accepts an SQLite DB file and compares the number of + /// GeoModel objects read from the SQLite .db file and the number of objects + /// subsequently restored in memory. It returns 'true' if the number of all + /// objects from the DB and in-memory match. It returns 'false' if the + /// numbers do not match. + static std::pair<std::string, bool> test_compareLoadedVsRestoredFromDB( + GMDBManager* db, unsigned loglevel = 0) { + std::string testname = "compareLoadedVsRestoredFromDB"; + if (loglevel >= 1) { + std::cout << "\n-- Test: " << testname << " -- \n"; + } + // setup the GeoModel reader + GeoModelIO::ReadGeoModel read(db); + // set loglevel of read action, if > 0 + if (loglevel > 0) { + read.setLogLevel(loglevel); + } + // load the data from the DB + read.loadDB(); + + // count all nodes loaded from the DB by the Read action + // the number of nodes is taken from the 'Read' GeoNodeAction itself, + // not the DB. + std::map<std::string, unsigned long> mmap_loaded = + GeoModelIO::IO::countLoadedNodesFromReadAction(read); + + // build the GeoModel tree from the loaded nodes + const GeoVPhysVol* rootVolume = read.buildGeoModel(); + + // count the number of all the restored nodes; + // i.e., the nodes of the restored in-memory GeoModel tree + std::map<std::string, unsigned long> mmap_restored = + GeoModelIO::IO::countTreeMemoryNodesFromVolume(rootVolume); + + bool testok = false; + if (mmap_loaded == mmap_restored) { + if (loglevel >= 1) { + std::cout << "OK! The number of loaded nodes is equal to the " + "number of restored nodes.\n"; + } + testok = true; + } else { + if (loglevel >= 1) { + std::cout << "!!! ERROR !!! The number of loaded nodes is " + "DIFFERENT from " + "the number of restored nodes!!!\n"; + if (loglevel >= 2) { + std::cout << "Loaded:\n"; + GeoModelIO::IO::printNodesMap(mmap_loaded); + std::cout << "Restored:\n"; + GeoModelIO::IO::printNodesMap(mmap_restored); + } + } + testok = false; + } + std::pair<std::string, bool> testout{testname, testok}; + return testout; + } + + static std::pair<bool, std::map<std::string, bool>> runAllTests( + const GeoVPhysVol* world, const unsigned loglevel = 0, const unsigned printtests = 0, const bool forceDelete = false) { + std::pair<bool, std::map<std::string, bool>> tests; + bool testall = false; + // TEST I/O: loading/restoring + std::pair<std::string, bool> test1 = + GeoModelIO::TestIO::test_compareWriteReadWriteFromVol(world, + loglevel, forceDelete); + std::pair<std::string, bool> test2 = + GeoModelIO::TestIO::test_compareMemoryVsRestoredFromVol(world, + loglevel, forceDelete); + // TEST I/O: DB + if (loglevel > 0) { + std::cout + << "\nSaving the 'world' volume to a .db file, for tests...\n"; + } + GMDBManager db = GeoModelIO::IO::saveToDB(world, "testdb.db", loglevel, forceDelete); + std::pair<std::string, bool> test3 = + GeoModelIO::TestIO::test_compareLoadedVsRestoredFromDB(&db, + loglevel); + // set an overall test return status, if all tests passed + if (test1.second && test2.second && test3.second) { + testall = true; + } + // gather and return results + std::map<std::string, bool> tmap; + tmap[test1.first] = test1.second; + tmap[test2.first] = test2.second; + tmap[test3.first] = test3.second; + tests.first = testall; + tests.second = tmap; + if (printtests >= 1) { + std::cout << "\n---\nThe overall result of the tests is: " + << testall << " [" << (testall ? "PASSED." : "FAILED!") + << "] \n"; + std::cout << "Single results: \n"; + for (auto& tt : tests.second) { + std::cout << "test: '" << tt.first << "' ==> " << tt.second + << " [" << (testall ? "PASSED." : "FAILED!") << "]" + << std::endl; + } + } + return tests; + } +}; // end class +} // namespace GeoModelIO + +#endif diff --git a/GeoModelIO/GeoModelIOHelpers/README.md b/GeoModelIO/GeoModelIOHelpers/README.md new file mode 100644 index 0000000000000000000000000000000000000000..8852af64f0e22fdc3373a522eb63a7708706956d --- /dev/null +++ b/GeoModelIO/GeoModelIOHelpers/README.md @@ -0,0 +1,4 @@ +# GeoModelIOHelpers + +This package contains helper functions to load/write a GeoModel .db file + diff --git a/GeoModelIO/GeoModelRead/CMakeLists.txt b/GeoModelIO/GeoModelRead/CMakeLists.txt index d91cdb77f81e46231db44c19bf38cfbe50dd0059..7a12ae38a31eb22d080296e3e4b0df3510730a0a 100644 --- a/GeoModelIO/GeoModelRead/CMakeLists.txt +++ b/GeoModelIO/GeoModelRead/CMakeLists.txt @@ -5,14 +5,6 @@ # major updates: rbianchi@cern.ch, 2018 ################################################################################ -# Set up configuration variables for turning certain build flags on or off. -option( GEOMODEL_IO_READ_DEBUG - "Turn on debug level output from the GeoModel I/O code by default" FALSE ) -option( GEOMODEL_IO_DEBUG_VERBOSE - "Turn on verbose level output from the GeoModel I/O code by default" FALSE ) -option( GEOMODEL_IO_READ_TIMING - "Turn on timing measurements in the GeoModel I/O code by default" FALSE ) - # Find the header and source files. file( GLOB SOURCES src/*.cpp ) file( GLOB HEADERS GeoModelRead/*.h GeoModelRead/*.tpp ) @@ -30,14 +22,6 @@ set_target_properties( GeoModelRead PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR} ) -# Set up custom build flags for the library. -foreach( _flag GEOMODEL_IO_READ_DEBUG GEOMODEL_IO_DEBUG_VERBOSE - GEOMODEL_IO_READ_TIMING ) - if( ${${_flag}} ) - target_compile_definitions( GeoModelRead PRIVATE ${_flag}=true ) - endif() -endforeach() - # Set up an alias with the same name that you would get by "finding" a pre-built # version of the library. add_library( GeoModelIO::GeoModelRead ALIAS GeoModelRead ) diff --git a/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.h b/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.h index 1b45039c88efaf258eb1975fa94d6a29e011ec03..d71a76a74b6b20ff31bfb19e9ec1f25ffc298d83 100644 --- a/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.h +++ b/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.h @@ -1,6 +1,5 @@ - /* - Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ /* @@ -20,9 +19,13 @@ * used for caching volumes that were built already The copyNumber was wrongly * used together with tableID and volID For details, see: * https://gitlab.cern.ch/GeoModelDev/GeoModel/-/issues/39 + * - Jan 2023, R.M.Bianchi <riccardo.maria.bianchi@cern.ch> + * Added getters to get number of GeoModel nodes + * restored from the * .db file * - 2023 Jan, R.M.Bianchi <riccardo.maria.bianchi@cern.ch> * Added method to get records out of custom tables from client code. - * + * - Feb 2023, R.M.Bianchi <riccardo.maria.bianchi@cern.ch> + * Added 'setLoglevel' method, to steer output messages */ #ifndef GeoModelRead_ReadGeoModel_H_ @@ -98,17 +101,55 @@ class ReadGeoModel { ReadGeoModel(GMDBManager* db, unsigned long* progress = nullptr); virtual ~ReadGeoModel(); - GeoPhysVol* buildGeoModel(); + const GeoVPhysVol* buildGeoModel(); + /// Set the 'loglevel', that is the level of output messages. + /// The loglevel is set to 0 by default, but it can be set + /// to a larger value. + /// Loglevel: + /// - 0 : Default + /// - 1 : Verbose + /// - 2 : Debug + void setLogLevel(unsigned loglevel) { m_loglevel = loglevel; }; + + // NB, this template method needs only the "publisher name" to be specified + // (i.e. the last suffix), since the first part of the table name get added + // automatically according to the data type it is templated on template <typename T, class N> std::map<T, N> getPublishedNodes( - std::string publisherName = "" /*optional variable*/); + std::string publisherName = "" /*optional variable*/, + bool doCheckTable = false); void printDBTable(const std::string& tableName) { m_dbManager->printAllRecords(tableName); } void printAllDBTables() { m_dbManager->printAllDBTables(); } + void loadDB(); + + unsigned long getNLogVols() { return m_logVols.size(); }; + unsigned long getNPhysVols() { return m_physVols.size(); }; + unsigned long getNFullPhysVols() { return m_fullPhysVols.size(); }; + unsigned long getNMaterials() { return m_materials.size(); }; + unsigned long getNElements() { return m_elements.size(); }; + unsigned long getNTransforms() { return m_transforms.size(); }; + unsigned long getNAlignableTransforms() { + return m_alignableTransforms.size(); + }; + unsigned long getNSerialDenominators() { + return m_serialDenominators.size(); + }; + unsigned long getNSerialIdentifiers() { + return m_serialIdentifiers.size(); + }; + unsigned long getNIdentifierTags() { return m_identifierTags.size(); }; + unsigned long getNSerialTransformers() { + return m_serialTransformers.size(); + }; + unsigned long getNFunctions() { return m_functions.size(); }; + unsigned long getNNameTags() { return m_nameTags.size(); }; + unsigned long getNShapes() { return m_shapes.size(); }; + unsigned long getNChildrenConnections() { return m_allchildren.size(); }; std::vector<std::vector<std::string>> getTableFromTableName( std::string tableName) { return m_dbManager->getTableRecords(tableName); @@ -130,7 +171,7 @@ class ReadGeoModel { void buildAllSerialTransformers(); void buildAllNameTags(); - GeoPhysVol* buildGeoModelPrivate(); + GeoVPhysVol* buildGeoModelPrivate(); GeoBox* buildDummyShape(); @@ -139,7 +180,7 @@ class ReadGeoModel { std::vector<std::vector<std::string>> records); void processParentChild(const std::vector<std::string>& parentchild); - GeoPhysVol* getRootVolume(); + GeoVPhysVol* getRootVolume(); GeoVPhysVol* buildVPhysVolInstance(const unsigned int id, const unsigned int tableId, @@ -321,6 +362,9 @@ class ReadGeoModel { //! container to store unknown shapes std::set<std::string> m_unknown_shapes; + + /// Stores the loglevel, the level of output messages + unsigned m_loglevel; }; } /* namespace GeoModelIO */ diff --git a/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.tpp b/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.tpp index 9e6d1ec7013528725f036c5377537a6faadd4dac..8c51af661550e11e9806648fc46f621a2222fcb0 100644 --- a/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.tpp +++ b/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.tpp @@ -14,15 +14,25 @@ namespace GeoModelIO { - template <typename T, class N> std::map<T,N> ReadGeoModel::getPublishedNodes( std::string publisherName /*optional variable*/) + template <typename T, class N> std::map<T,N> ReadGeoModel::getPublishedNodes(std::string publisherName, bool doCheckTable /*optional variables*/) { + + std::map<T, N> mapNodes; std::string keyType = ""; std::vector<std::vector<std::string>> vecRecords; if constexpr ( std::is_same_v<GeoFullPhysVol*, N> ) { + if(doCheckTable){ + bool tableExists = m_dbManager->checkTable("PublishedFullPhysVols_"+publisherName); + if(!tableExists) return mapNodes; + } vecRecords = m_dbManager->getPublishedFPVTable( publisherName ); } else if constexpr ( std::is_same_v<GeoAlignableTransform*, N> ) { + if(doCheckTable){ + bool tableExists = m_dbManager->checkTable("PublishedAlignableTransforms_"+publisherName); + if(!tableExists) return mapNodes; + } vecRecords = m_dbManager->getPublishedAXFTable( publisherName ); } else { std::cout << "ERROR! The node type '" << typeid(N).name() diff --git a/GeoModelIO/GeoModelRead/examples/hellogeo/CMakeLists.txt.example b/GeoModelIO/GeoModelRead/examples/hellogeo/CMakeLists.txt.example index 591b24abc759daef2745cfe1fc0e9c8cbdf2d633..65aaaad5408f9b625ec9f409ad618170099d4389 100644 --- a/GeoModelIO/GeoModelRead/examples/hellogeo/CMakeLists.txt.example +++ b/GeoModelIO/GeoModelRead/examples/hellogeo/CMakeLists.txt.example @@ -3,7 +3,7 @@ # author: Riccardo Maria BIANCHI <rbianchi@cern.ch> - Nov, 2018 ################################################################################ -cmake_minimum_required(VERSION 3.1.0) +cmake_minimum_required(VERSION 3.16...3.26) project(hellogeo) diff --git a/GeoModelIO/GeoModelRead/src/ReadGeoModel.cpp b/GeoModelIO/GeoModelRead/src/ReadGeoModel.cpp index 768e4706a1a734dbd04bf1e6eb6368799f23c2c1..3cd0838f6b34bd2d0ff1d23efb98a8c2d4c7b33d 100644 --- a/GeoModelIO/GeoModelRead/src/ReadGeoModel.cpp +++ b/GeoModelIO/GeoModelRead/src/ReadGeoModel.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ /* @@ -13,15 +13,18 @@ * - Mar 2020, R.M.Bianchi * - Mar 2020, boudreau * - May 2020, R.M.Bianchi - * - Aug 2020, R.M.Bianchi - Added support to read published FullPhysVols and AlignableTransforms back in - * - Aug 2021, R.M.Bianchi <riccardo.maria.bianchi@cern.ch> - Added support for GeoSerialIdentifier and GeoIdentifierTag + * - Aug 2020, R.M.Bianchi - Added support to read published FullPhysVols and + * AlignableTransforms back in + * - Aug 2021, R.M.Bianchi <riccardo.maria.bianchi@cern.ch> - Added support for + * GeoSerialIdentifier and GeoIdentifierTag * - Jun 2022, R.M.Bianchi <riccardo.maria.bianchi@cern.ch> - * Fixed the duplication of VPhysVol instances due to a wrong key used for caching volumes that were built already + * Fixed the duplication of VPhysVol instances due to a wrong key, + * which was used for caching volumes that were built already. * The copyNumber was wrongly used together with tableID and volID - * For details, see: https://gitlab.cern.ch/GeoModelDev/GeoModel/-/issues/39 + * For details, see: + * https://gitlab.cern.ch/GeoModelDev/GeoModel/-/issues/39 */ - // local includes #include "GeoModelRead/ReadGeoModel.h" @@ -29,657 +32,864 @@ #include "TFPersistification/TransFunctionInterpreter.h" // GeoModelKernel includes -#include "GeoModelKernel/GeoUtilFunctions.h" -#include "GeoModelKernel/GeoTransform.h" #include "GeoModelKernel/GeoAlignableTransform.h" -#include "GeoModelKernel/GeoSerialTransformer.h" -#include "GeoModelKernel/GeoSerialDenominator.h" -#include "GeoModelKernel/GeoSerialIdentifier.h" +#include "GeoModelKernel/GeoElement.h" +#include "GeoModelKernel/GeoFullPhysVol.h" +#include "GeoModelKernel/GeoGraphNode.h" #include "GeoModelKernel/GeoIdentifierTag.h" +#include "GeoModelKernel/GeoLogVol.h" #include "GeoModelKernel/GeoMaterial.h" -#include "GeoModelKernel/GeoElement.h" #include "GeoModelKernel/GeoNameTag.h" -#include "GeoModelKernel/GeoLogVol.h" -#include "GeoModelKernel/GeoVPhysVol.h" #include "GeoModelKernel/GeoPhysVol.h" -#include "GeoModelKernel/GeoFullPhysVol.h" -#include "GeoModelKernel/GeoGraphNode.h" +#include "GeoModelKernel/GeoSerialDenominator.h" +#include "GeoModelKernel/GeoSerialIdentifier.h" +#include "GeoModelKernel/GeoSerialTransformer.h" +#include "GeoModelKernel/GeoTransform.h" +#include "GeoModelKernel/GeoUtilFunctions.h" +#include "GeoModelKernel/GeoVPhysVol.h" // GeoModel shapes -#include "GeoModelKernel/GeoShape.h" #include "GeoModelKernel/GeoBox.h" #include "GeoModelKernel/GeoCons.h" +#include "GeoModelKernel/GeoGenericTrap.h" #include "GeoModelKernel/GeoPara.h" #include "GeoModelKernel/GeoPcon.h" #include "GeoModelKernel/GeoPgon.h" +#include "GeoModelKernel/GeoShape.h" +#include "GeoModelKernel/GeoShapeIntersection.h" +#include "GeoModelKernel/GeoShapeShift.h" +#include "GeoModelKernel/GeoShapeSubtraction.h" +#include "GeoModelKernel/GeoShapeUnion.h" #include "GeoModelKernel/GeoSimplePolygonBrep.h" #include "GeoModelKernel/GeoTessellatedSolid.h" -#include "GeoModelKernel/GeoGenericTrap.h" +#include "GeoModelKernel/GeoTorus.h" #include "GeoModelKernel/GeoTrap.h" -#include "GeoModelKernel/GeoTwistedTrap.h" #include "GeoModelKernel/GeoTrd.h" #include "GeoModelKernel/GeoTube.h" #include "GeoModelKernel/GeoTubs.h" -#include "GeoModelKernel/GeoTorus.h" -#include "GeoModelKernel/GeoShapeIntersection.h" -#include "GeoModelKernel/GeoShapeShift.h" -#include "GeoModelKernel/GeoShapeSubtraction.h" -#include "GeoModelKernel/GeoShapeUnion.h" +#include "GeoModelKernel/GeoTwistedTrap.h" #include "GeoModelKernel/GeoUnidentifiedShape.h" - // Units #include "GeoModelKernel/Units.h" -#define SYSTEM_OF_UNITS GeoModelKernelUnits // so we will get, e.g., 'GeoModelKernelUnits::cm' +#define SYSTEM_OF_UNITS \ + GeoModelKernelUnits // so we will get, e.g., 'GeoModelKernelUnits::cm' -//VP1Base -// TODO: we should get rid of VP1Base::VP1Msg dependency, since GeoModelRead should not depend on VP1 packages. Maybe we can move VP1Msg to a standalone package. -//#include "VP1Base/VP1Msg.h" +// VP1Base +// TODO: we should get rid of VP1Base::VP1Msg dependency, since GeoModelRead +// should not depend on VP1 packages. Maybe we can move VP1Msg to a standalone +// package. +// #include "VP1Base/VP1Msg.h" // C++ includes #include <stdlib.h> /* exit, EXIT_FAILURE */ -#include <stdexcept> + +#include <chrono> /* system_clock */ +#include <cstdlib> /* std::getenv */ +#include <ctime> /* std::time */ #include <future> #include <mutex> -#include <chrono> /* system_clock */ -#include <ctime> /* std::time */ -#include <cstdlib> /* std::getenv */ -#include <vector> +#include <stdexcept> +#include <thread> #include <unordered_map> #include <unordered_set> -#include <thread> - +#include <vector> -// mutexes for synchronized access to containers and output streams in multi-threading mode +// mutexes for synchronized access to containers and output streams in +// multi-threading mode std::mutex muxVPhysVol; std::mutex muxCout; - using namespace GeoGenfun; using namespace GeoXF; // Set default (false) values for the debugging variables. #ifndef GEOMODEL_IO_READ_DEBUG #define GEOMODEL_IO_READ_DEBUG false -#endif // not GEOMODEL_IO_READ_DEBUG +#endif // not GEOMODEL_IO_READ_DEBUG #ifndef GEOMODEL_IO_DEBUG_VERBOSE #define GEOMODEL_IO_DEBUG_VERBOSE false -#endif // not GEOMODEL_IO_DEBUG_VERBOSE +#endif // not GEOMODEL_IO_DEBUG_VERBOSE #ifndef GEOMODEL_IO_READ_TIMING #define GEOMODEL_IO_READ_TIMING false -#endif // not GEOMODEL_IO_READ_TIMING +#endif // not GEOMODEL_IO_READ_TIMING namespace GeoModelIO { -ReadGeoModel::ReadGeoModel(GMDBManager* db, unsigned long* progress) : m_deepDebug(GEOMODEL_IO_DEBUG_VERBOSE), - m_debug(GEOMODEL_IO_READ_DEBUG), m_timing(GEOMODEL_IO_READ_TIMING), m_runMultithreaded(false), - m_runMultithreaded_nThreads(0), m_progress(nullptr) -{ - // Check if the user asked for debug messages - if ( "" != getEnvVar("GEOMODEL_ENV_IO_READ_DEBUG")) { - m_debug = true; - std::cout << "You defined the GEOMODEL_ENV_IO_DEBUG variable, so you will see a verbose output." << std::endl; - } - // Check if the user asked for verbose debug messages - if ( "" != getEnvVar("GEOMODEL_ENV_IO_DEBUG_VERBOSE")) { - m_deepDebug = true; - std::cout << "You defined the GEOMODEL_ENV_IO_READ_DEBUG_VERBOSE variable, so you will see a verbose output." << std::endl; - } - // Check if the user asked for timing output - if ( "" != getEnvVar("GEOMODEL_ENV_IO_READ_TIMING")) { - m_timing = true; - std::cout << "You defined the GEOMODEL_ENV_IO_READ_TIMING variable, so you will see a timing measurement in the output." << std::endl; - } - - if ( progress != nullptr) { - m_progress = progress; - } - - // open the geometry file - m_dbManager = db; - if (m_dbManager->checkIsDBOpen()) { - if (m_debug) std::cout << "OK! Database is open!"; - } - else { - std::cout << "ERROR!! Database is NOT open!"; - return; - } - // build caches - m_dbManager->loadGeoNodeTypesAndBuildCache(); - m_dbManager->createTableDataCaches(); - - - // Check if the user asked for running in serial or multi-threading mode - if ( "" != getEnvVar("GEOMODEL_ENV_IO_NTHREADS")) - { - int nThreads = std::stoi(getEnvVar("GEOMODEL_ENV_IO_NTHREADS")); - if (nThreads == 0) { - std::cout << "Info: You set the GEOMODEL_ENV_IO_NTHREADS to '" << nThreads << "'; thus, GeoModelIO will be run in serial mode." << std::endl; - m_runMultithreaded_nThreads = nThreads; - m_runMultithreaded = false; - } else if( nThreads > 0 ) { - std::cout << "Info: You set the GEOMODEL_ENV_IO_NTHREADS to '" << nThreads << "'; thus, GeoModelIO will use that number of worker threads." << std::endl; - m_runMultithreaded_nThreads = nThreads; - m_runMultithreaded = true; - } else if (nThreads == -1) { - std::cout << "Info: You set the GEOMODEL_ENV_IO_NTHREADS to '" << nThreads << "'; thus, GeoModelIO will use the number of threads supported by the platform." << std::endl; - m_runMultithreaded_nThreads = nThreads; - m_runMultithreaded = true; - } - } - // if the user did not specify the number of threads, then we just use the hardware-supported number of threads on the platform - else { - m_runMultithreaded_nThreads = -1; - m_runMultithreaded = true; - } +ReadGeoModel::ReadGeoModel(GMDBManager* db, unsigned long* progress) + : m_loglevel(0), + m_deepDebug(GEOMODEL_IO_DEBUG_VERBOSE), + m_debug(GEOMODEL_IO_READ_DEBUG), + m_timing(GEOMODEL_IO_READ_TIMING), + m_runMultithreaded(false), + m_runMultithreaded_nThreads(0), + m_progress(nullptr) { + // Check if the user asked for debug messages + if ("" != getEnvVar("GEOMODEL_ENV_IO_LOGLEVEL_1")) { + m_loglevel = 1; + std::cout << "You defined the GEOMODEL_ENV_IO_DEBUG variable, so you " + "will see a verbose output." + << std::endl; + } + // Check if the user asked for verbose debug messages + if ("" != getEnvVar("GEOMODEL_ENV_IO_LOGLEVEL_2")) { + m_loglevel = 2; + std::cout << "You defined the GEOMODEL_ENV_IO_READ_DEBUG_VERBOSE " + "variable, so you will see a verbose output." + << std::endl; + } + // Check if the user asked for timing output + if ("" != getEnvVar("GEOMODEL_ENV_IO_READ_TIMING")) { + m_timing = true; + std::cout << "You defined the GEOMODEL_ENV_IO_READ_TIMING variable, so " + "you will see a timing measurement in the output." + << std::endl; + } + + if (progress != nullptr) { + m_progress = progress; + } + + // open the geometry file + m_dbManager = db; + if (m_dbManager->checkIsDBOpen()) { + if (m_loglevel >= 1) std::cout << "OK! Database is open!"; + } else { + std::cout << "ERROR!! Database is NOT open!"; + return; + } + // build caches + m_dbManager->loadGeoNodeTypesAndBuildCache(); + m_dbManager->createTableDataCaches(); + + // Check if the user asked for running in serial or multi-threading mode + if ("" != getEnvVar("GEOMODEL_ENV_IO_NTHREADS")) { + int nThreads = std::stoi(getEnvVar("GEOMODEL_ENV_IO_NTHREADS")); + if (nThreads == 0) { + std::cout << "Info: You set the GEOMODEL_ENV_IO_NTHREADS to '" + << nThreads + << "'; thus, GeoModelIO will be run in serial mode." + << std::endl; + m_runMultithreaded_nThreads = nThreads; + m_runMultithreaded = false; + } else if (nThreads > 0) { + std::cout + << "Info: You set the GEOMODEL_ENV_IO_NTHREADS to '" << nThreads + << "'; thus, GeoModelIO will use that number of worker threads." + << std::endl; + m_runMultithreaded_nThreads = nThreads; + m_runMultithreaded = true; + } else if (nThreads == -1) { + std::cout << "Info: You set the GEOMODEL_ENV_IO_NTHREADS to '" + << nThreads + << "'; thus, GeoModelIO will use the number of threads " + "supported by the platform." + << std::endl; + m_runMultithreaded_nThreads = nThreads; + m_runMultithreaded = true; + } + } + // if the user did not specify the number of threads, then we just use the + // hardware-supported number of threads on the platform + else { + m_runMultithreaded_nThreads = -1; + m_runMultithreaded = true; + } + + // load the data from the DB + loadDB(); } ReadGeoModel::~ReadGeoModel() { - // FIXME: some cleaning...?? + // FIXME: some cleaning...?? } - // FIXME: TODO: move to an utility class -std::string ReadGeoModel::getEnvVar( std::string const & key ) const -{ - char * val = std::getenv( key.c_str() ); +// FIXME: TODO: move to an utility class +std::string ReadGeoModel::getEnvVar(std::string const& key) const { + char* val = std::getenv(key.c_str()); return val == NULL ? std::string("") : std::string(val); } -GeoPhysVol* ReadGeoModel::buildGeoModel() -{ - if (m_deepDebug) std::cout << "ReadGeoModel::buildGeoModel()" << std::endl; +const GeoVPhysVol* ReadGeoModel::buildGeoModel() { + if (m_loglevel >= 2) + std::cout << "ReadGeoModel::buildGeoModel()" << std::endl; - GeoPhysVol* rootVolume = buildGeoModelPrivate(); + GeoVPhysVol* rootVolume = buildGeoModelPrivate(); - // warn the user if there are unknown/unhalded shapes - if (m_unknown_shapes.size() > 0) { - std::cout << "\tWARNING!! There were unknwon shapes:" << std::endl; - for ( auto it = m_unknown_shapes.begin(); it != m_unknown_shapes.end(); it++ ) { - std::cout << "\t\t---> " << *it << std::endl; - } - std::cout << "\tRemember: unknown shapes are rendered with a dummy cube of 30cm side length.\n\n" << std::endl; - } + // warn the user if there are unknown/unhalded shapes + if (m_unknown_shapes.size() > 0) { + std::cout << "\tWARNING!! There were unknwon shapes:" << std::endl; + for (auto it = m_unknown_shapes.begin(); it != m_unknown_shapes.end(); + it++) { + std::cout << "\t\t---> " << *it << std::endl; + } + std::cout << "\tRemember: unknown shapes are rendered with a dummy " + "cube of 30cm side length.\n\n" + << std::endl; + } - return rootVolume; + return rootVolume; +} + +void ReadGeoModel::loadDB() { + // *** get all data from the DB *** + std::chrono::system_clock::time_point start = + std::chrono::system_clock::now(); // timing: get start time + // get all GeoModel nodes from the DB + m_logVols = m_dbManager->getTableFromNodeType("GeoLogVol"); + m_shapes = m_dbManager->getTableFromNodeType("GeoShape"); + m_materials = m_dbManager->getTableFromNodeType("GeoMaterial"); + m_elements = m_dbManager->getTableFromNodeType("GeoElement"); + m_functions = m_dbManager->getTableFromNodeType("Function"); + m_physVols = m_dbManager->getTableFromNodeType("GeoPhysVol"); + m_fullPhysVols = m_dbManager->getTableFromNodeType("GeoFullPhysVol"); + m_transforms = m_dbManager->getTableFromNodeType("GeoTransform"); + m_alignableTransforms = + m_dbManager->getTableFromNodeType("GeoAlignableTransform"); + m_serialDenominators = + m_dbManager->getTableFromNodeType("GeoSerialDenominator"); + m_serialIdentifiers = + m_dbManager->getTableFromNodeType("GeoSerialIdentifier"); + m_identifierTags = m_dbManager->getTableFromNodeType("GeoIdentifierTag"); + m_serialTransformers = + m_dbManager->getTableFromNodeType("GeoSerialTransformer"); + m_nameTags = m_dbManager->getTableFromNodeType("GeoNameTag"); + // get the children table from DB + m_allchildren = m_dbManager->getChildrenTable(); + // get the root volume data + m_root_vol_data = m_dbManager->getRootPhysVol(); + // get DB metadata + m_tableID_toTableName = m_dbManager->getAll_TableIDsNodeTypes(); + m_tableName_toTableID = m_dbManager->getAll_NodeTypesTableIDs(); + + auto end = std::chrono::system_clock::now(); // timing: get end time + auto diff = + std::chrono::duration_cast<std::chrono::seconds>(end - start).count(); + if (m_timing || (m_loglevel >= 1)) { + std::cout << "*** Time taken to fetch GeoModel data from the database: " + << diff << " [s]" << std::endl; + } } +GeoVPhysVol* ReadGeoModel::buildGeoModelPrivate() { + // *** build all nodes *** + std::chrono::system_clock::time_point start = + std::chrono::system_clock::now(); // timing: get start time + // parallel mode: + if (m_runMultithreaded) { + if (m_loglevel >= 1) + std::cout << "Building nodes concurrently..." << std::endl; + std::thread t2(&ReadGeoModel::buildAllElements, this); + // std::thread t7(&ReadGeoModel::buildAllFunctions, this); // + // FIXME: implement cache for Functions + + std::thread t8(&ReadGeoModel::buildAllTransforms, this); + std::thread t9(&ReadGeoModel::buildAllAlignableTransforms, this); + std::thread t10(&ReadGeoModel::buildAllSerialDenominators, this); + std::thread t13(&ReadGeoModel::buildAllSerialIdentifiers, this); + std::thread t14(&ReadGeoModel::buildAllIdentifierTags, this); + std::thread t11(&ReadGeoModel::buildAllNameTags, this); + + t8.join(); // ok, all Transforms have been built + t9.join(); // ok, all AlignableTransforms have been built + // needs Transforms and AlignableTransforms for Shift boolean shapes + std::thread t1(&ReadGeoModel::buildAllShapes, this); + + t2.join(); // ok, all Elements have been built + // needs Elements + std::thread t3(&ReadGeoModel::buildAllMaterials, this); + + t1.join(); // ok, all Shapes have been built + t3.join(); // ok, all Materials have been built + // needs Shapes and Materials + std::thread t4(&ReadGeoModel::buildAllLogVols, this); + + t4.join(); // ok, all LogVols have been built + // needs LogVols + std::thread t5(&ReadGeoModel::buildAllPhysVols, this); + std::thread t6(&ReadGeoModel::buildAllFullPhysVols, this); + + t5.join(); // ok, all PhysVols have been built + t6.join(); // ok, all FullPhysVols have been built + // t7.join(); // ok, all Functions have been built + // needs Functions, PhysVols, FullPhysVols + std::thread t12(&ReadGeoModel::buildAllSerialTransformers, this); + + t10.join(); // ok, all SerialDenominators have been built + t11.join(); // ok, all NameTags have been built + t12.join(); // ok, all SerialTransformers have been built + t13.join(); // ok, all SerialIdentifiers have been built + t14.join(); // ok, all IdentifierTags have been built + } + // serial mode: + else { + if (m_loglevel >= 1) + std::cout << "Building nodes serially..." << std::endl; + buildAllElements(); + // buildAllFunctions(); + buildAllTransforms(); + buildAllAlignableTransforms(); + buildAllSerialDenominators(); + buildAllSerialIdentifiers(); + buildAllIdentifierTags(); + buildAllNameTags(); + buildAllShapes(); + buildAllMaterials(); + buildAllLogVols(); + buildAllPhysVols(); + buildAllFullPhysVols(); + buildAllSerialTransformers(); + } + auto end = std::chrono::system_clock::now(); // timing: get end time + auto diff = + std::chrono::duration_cast<std::chrono::seconds>(end - start).count(); + if (m_timing || (m_loglevel >= 1)) { + std::cout << "*** Time taken to build all GeoModel nodes: " << diff + << " [s]" << std::endl; + } -GeoPhysVol* ReadGeoModel::buildGeoModelPrivate() -{ - // *** get all data from the DB *** - std::chrono::system_clock::time_point start = std::chrono::system_clock::now(); // timing: get start time - // get all GeoModel nodes from the DB - m_logVols = m_dbManager->getTableFromNodeType("GeoLogVol"); - m_shapes = m_dbManager->getTableFromNodeType("GeoShape"); - m_materials = m_dbManager->getTableFromNodeType("GeoMaterial"); - m_elements = m_dbManager->getTableFromNodeType("GeoElement"); - m_functions = m_dbManager->getTableFromNodeType("Function"); - m_physVols = m_dbManager->getTableFromNodeType("GeoPhysVol"); - m_fullPhysVols = m_dbManager->getTableFromNodeType("GeoFullPhysVol"); - m_transforms = m_dbManager->getTableFromNodeType("GeoTransform"); - m_alignableTransforms = m_dbManager->getTableFromNodeType("GeoAlignableTransform"); - m_serialDenominators = m_dbManager->getTableFromNodeType("GeoSerialDenominator"); - m_serialIdentifiers = m_dbManager->getTableFromNodeType("GeoSerialIdentifier"); - m_identifierTags = m_dbManager->getTableFromNodeType("GeoIdentifierTag"); - m_serialTransformers = m_dbManager->getTableFromNodeType("GeoSerialTransformer"); - m_nameTags = m_dbManager->getTableFromNodeType("GeoNameTag"); - // get the children table from DB - m_allchildren = m_dbManager->getChildrenTable(); - // get the root volume data - m_root_vol_data = m_dbManager->getRootPhysVol(); - // get DB metadata - m_tableID_toTableName = m_dbManager->getAll_TableIDsNodeTypes(); - m_tableName_toTableID = m_dbManager->getAll_NodeTypesTableIDs(); - - auto end = std::chrono::system_clock::now(); // timing: get end time - auto diff = std::chrono::duration_cast < std::chrono::seconds > (end - start).count(); - if (m_timing || m_debug || m_deepDebug) { - std::cout << "*** Time taken to fetch GeoModel data from the database: " << diff << " [s]" << std::endl; - } - - // *** build all nodes *** - start = std::chrono::system_clock::now(); // timing: get start time - // parallel mode: - if (m_runMultithreaded) { - if (m_debug) std::cout << "Building nodes concurrently..." << std::endl; - std::thread t2(&ReadGeoModel::buildAllElements, this); - // std::thread t7(&ReadGeoModel::buildAllFunctions, this); // FIXME: implement cache for Functions - - std::thread t8(&ReadGeoModel::buildAllTransforms, this); - std::thread t9(&ReadGeoModel::buildAllAlignableTransforms, this); - std::thread t10(&ReadGeoModel::buildAllSerialDenominators, this); - std::thread t13(&ReadGeoModel::buildAllSerialIdentifiers, this); - std::thread t14(&ReadGeoModel::buildAllIdentifierTags, this); - std::thread t11(&ReadGeoModel::buildAllNameTags, this); - - t8.join(); // ok, all Transforms have been built - t9.join(); // ok, all AlignableTransforms have been built - // needs Transforms and AlignableTransforms for Shift boolean shapes - std::thread t1(&ReadGeoModel::buildAllShapes, this); - - t2.join(); // ok, all Elements have been built - // needs Elements - std::thread t3(&ReadGeoModel::buildAllMaterials, this); - - t1.join(); // ok, all Shapes have been built - t3.join(); // ok, all Materials have been built - // needs Shapes and Materials - std::thread t4(&ReadGeoModel::buildAllLogVols, this); - - t4.join(); // ok, all LogVols have been built - // needs LogVols - std::thread t5(&ReadGeoModel::buildAllPhysVols, this); - std::thread t6(&ReadGeoModel::buildAllFullPhysVols, this); - - t5.join(); // ok, all PhysVols have been built - t6.join(); // ok, all FullPhysVols have been built - // t7.join(); // ok, all Functions have been built - // needs Functions, PhysVols, FullPhysVols - std::thread t12(&ReadGeoModel::buildAllSerialTransformers, this); - - t10.join(); // ok, all SerialDenominators have been built - t11.join(); // ok, all NameTags have been built - t12.join(); // ok, all SerialTransformers have been built - t13.join(); // ok, all SerialIdentifiers have been built - t14.join(); // ok, all IdentifierTags have been built - } - // serial mode: - else { - if (m_debug) std::cout << "Building nodes serially..." << std::endl; - buildAllElements(); - // buildAllFunctions(); - buildAllTransforms(); - buildAllAlignableTransforms(); - buildAllSerialDenominators(); - buildAllSerialIdentifiers(); - buildAllIdentifierTags(); - buildAllNameTags(); - buildAllShapes(); - buildAllMaterials(); - buildAllLogVols(); - buildAllPhysVols(); - buildAllFullPhysVols(); - buildAllSerialTransformers(); - } - end = std::chrono::system_clock::now(); // timing: get end time - diff = std::chrono::duration_cast < std::chrono::seconds > (end - start).count(); - if (m_timing || m_debug || m_deepDebug) { - std::cout << "*** Time taken to build all GeoModel nodes: " << diff << " [s]" << std::endl; - } - - // *** recreate all mother-daughter relatioships between nodes *** - start = std::chrono::system_clock::now(); // timing: get start time - loopOverAllChildrenInBunches(); - end = std::chrono::system_clock::now(); // timing: get end time - diff = std::chrono::duration_cast < std::chrono::seconds > (end - start).count(); - if (m_timing || m_debug || m_deepDebug) { - std::cout << "*** Time taken to recreate all mother-daughter relationships between nodes of the GeoModel tree: " << diff << " [s]" << std::endl; - } - - return getRootVolume(); -} + // *** recreate all mother-daughter relatioships between nodes *** + start = std::chrono::system_clock::now(); // timing: get start time + loopOverAllChildrenInBunches(); + end = std::chrono::system_clock::now(); // timing: get end time + diff = + std::chrono::duration_cast<std::chrono::seconds>(end - start).count(); + if (m_timing || (m_loglevel >= 1)) { + std::cout << "*** Time taken to recreate all mother-daughter " + "relationships between nodes of the GeoModel tree: " + << diff << " [s]" << std::endl; + } + return getRootVolume(); +} //---------------------------------------- // loop over parent-child relationship data - void ReadGeoModel::loopOverAllChildrenRecords(std::vector<std::vector<std::string>> records) -{ +void ReadGeoModel::loopOverAllChildrenRecords( + std::vector<std::vector<std::string>> records) { + int nChildrenRecords = records.size(); - int nChildrenRecords = records.size(); + if (m_loglevel >= 1) { + muxCout.lock(); + std::cout << "\nReadGeoModel::loopOverAllChildrenRecords -- Thread " + << std::this_thread::get_id() << " - processing " + << nChildrenRecords << " keys..." << std::endl; + muxCout.unlock(); + } - if (m_debug || m_deepDebug) { - muxCout.lock(); - std::cout << "\nReadGeoModel::loopOverAllChildrenRecords -- Thread " << std::this_thread::get_id() << " - processing " << nChildrenRecords << " keys..." << std::endl; - muxCout.unlock(); - } - -// // Get Start Time -// std::chrono::system_clock::time_point start = std::chrono::system_clock::now(); - - for ( auto& record : records ) { - processParentChild( record ); - } - -// // Get End Time -// auto end = std::chrono::system_clock::now(); -// auto diff = std::chrono::duration_cast < std::chrono::seconds > (end - start).count(); -// -// if (m_timing || m_debug || m_deepDebug) { -// muxCout.lock(); -// std::cout << "Time Taken to process " << nChildrenRecords << " parent-child relationships = " << diff << " Seconds" << std::endl; -// muxCout.unlock(); -// } -} + // // Get Start Time + // std::chrono::system_clock::time_point start = + // std::chrono::system_clock::now(); + for (auto& record : records) { + processParentChild(record); + } -//! Iterate over the list of shapes, build them all, and store their pointers -void ReadGeoModel::buildAllShapes() -{ - if (m_debug) std::cout << "Building all shapes...\n"; - size_t nSize = m_shapes.size(); - m_memMapShapes.reserve( nSize*2 ); // TODO: check if *2 is good or redundant... - for (unsigned int ii=0; ii<nSize; ++ii) { - const unsigned int shapeID = std::stoi(m_shapes[ii][0]); - type_shapes_boolean_info shapes_info_sub; // tuple to store the boolean shapes to complete at a second stage - buildShape(shapeID, &shapes_info_sub); - createBooleanShapeOperands(&shapes_info_sub); - } - if (nSize>0) std::cout << "All " << nSize << " Shapes have been built!\n"; -} - -//! Iterate over the list of GeoSerialDenominator nodes, build them all, and store their pointers -void ReadGeoModel::buildAllSerialDenominators() -{ - if (m_debug) std::cout << "Building all SerialDenominator nodes...\n"; - size_t nSize = m_serialDenominators.size(); - m_memMapSerialDenominators.reserve( nSize*2 ); // TODO: check if *2 is good or redundant... - for (unsigned int ii=0; ii<nSize; ++ii) { - //const unsigned int nodeID = std::stoi(m_serialDenominators[ii][0]); // RMB: not used at the moment, commented to avoid warnings - const std::string baseName = m_serialDenominators[ii][1]; - GeoSerialDenominator* nodePtr = new GeoSerialDenominator(baseName); - storeBuiltSerialDenominator(nodePtr); - } - if (nSize>0) std::cout << "All " << nSize << " SerialDenominators have been built!\n"; -} - -//! Iterate over the list of GeoSerialIdentifier nodes, build them all, and store their pointers -void ReadGeoModel::buildAllSerialIdentifiers() -{ - if (m_debug) std::cout << "Building all SerialIdentifier nodes...\n"; - size_t nSize = m_serialIdentifiers.size(); - m_memMapSerialIdentifiers.reserve( nSize*2 ); // TODO: check if *2 is good or redundant... - for (unsigned int ii=0; ii<nSize; ++ii) { - //const unsigned int nodeID = std::stoi(m_seriaIdentifiers[ii][0]); // RMB: not used at the moment, commented to avoid warnings - const int baseId = std::stoi(m_serialIdentifiers[ii][1]); - GeoSerialIdentifier* nodePtr = new GeoSerialIdentifier(baseId); - storeBuiltSerialIdentifier(nodePtr); - } - if (nSize>0) std::cout << "All " << nSize << " SerialIdentifiers have been built!\n"; -} - -//! Iterate over the list of GeoIdentifierTag nodes, build them all, and store their pointers -void ReadGeoModel::buildAllIdentifierTags() -{ - if (m_debug) std::cout << "Building all IdentifierTag nodes...\n"; - size_t nSize = m_identifierTags.size(); - m_memMapIdentifierTags.reserve( nSize*2 ); // TODO: check if *2 is good or redundant... - for (unsigned int ii=0; ii<nSize; ++ii) { - //const unsigned int nodeID = std::stoi(m_identifierTags[ii][0]); // RMB: not used at the moment, commented to avoid warnings - const int identifier = std::stoi(m_identifierTags[ii][1]); - GeoIdentifierTag* nodePtr = new GeoIdentifierTag(identifier); - storeBuiltIdentifierTag(nodePtr); - } - if (nSize>0) std::cout << "All " << nSize << " SerialIdentifiers have been built!\n"; + // // Get End Time + // auto end = std::chrono::system_clock::now(); + // auto diff = std::chrono::duration_cast < std::chrono::seconds > (end + // - start).count(); + // + // if (m_timing || (m_loglevel >= 1)) { + // muxCout.lock(); + // std::cout << "Time Taken to process " << nChildrenRecords << " + // parent-child relationships = " << diff << " Seconds" << std::endl; + // muxCout.unlock(); + // } +} + +//! Iterate over the list of shapes, build them all, and store their +//! pointers +void ReadGeoModel::buildAllShapes() { + if (m_loglevel >= 1) std::cout << "Building all shapes...\n"; + size_t nSize = m_shapes.size(); + m_memMapShapes.reserve(nSize * + 2); // TODO: check if *2 is good or redundant... + for (unsigned int ii = 0; ii < nSize; ++ii) { + const unsigned int shapeID = std::stoi(m_shapes[ii][0]); + type_shapes_boolean_info + shapes_info_sub; // tuple to store the boolean shapes to + // complete at a second stage + buildShape(shapeID, &shapes_info_sub); + createBooleanShapeOperands(&shapes_info_sub); + } + if (nSize > 0) std::cout << "All " << nSize << " Shapes have been built!\n"; +} + +//! Iterate over the list of GeoSerialDenominator nodes, build them all, and +//! store their pointers +void ReadGeoModel::buildAllSerialDenominators() { + if (m_loglevel >= 1) + std::cout << "Building all SerialDenominator nodes...\n"; + size_t nSize = m_serialDenominators.size(); + m_memMapSerialDenominators.reserve( + nSize * 2); // TODO: check if *2 is good or redundant... + for (unsigned int ii = 0; ii < nSize; ++ii) { + // const unsigned int nodeID = + // std::stoi(m_serialDenominators[ii][0]); + // // RMB: not used at the moment, commented to avoid warnings + const std::string baseName = m_serialDenominators[ii][1]; + GeoSerialDenominator* nodePtr = new GeoSerialDenominator(baseName); + storeBuiltSerialDenominator(nodePtr); + } + if (nSize > 0) + std::cout << "All " << nSize + << " SerialDenominators have been built!\n"; +} + +//! Iterate over the list of GeoSerialIdentifier nodes, build them all, and +//! store their pointers +void ReadGeoModel::buildAllSerialIdentifiers() { + if (m_loglevel >= 1) + std::cout << "Building all SerialIdentifier nodes...\n"; + size_t nSize = m_serialIdentifiers.size(); + m_memMapSerialIdentifiers.reserve( + nSize * 2); // TODO: check if *2 is good or redundant... + for (unsigned int ii = 0; ii < nSize; ++ii) { + // const unsigned int nodeID = std::stoi(m_seriaIdentifiers[ii][0]); + // // RMB: not used at the moment, commented to avoid warnings + const int baseId = std::stoi(m_serialIdentifiers[ii][1]); + GeoSerialIdentifier* nodePtr = new GeoSerialIdentifier(baseId); + storeBuiltSerialIdentifier(nodePtr); + } + if (nSize > 0) + std::cout << "All " << nSize << " SerialIdentifiers have been built!\n"; +} + +//! Iterate over the list of GeoIdentifierTag nodes, build them all, and +//! store their pointers +void ReadGeoModel::buildAllIdentifierTags() { + if (m_loglevel >= 1) std::cout << "Building all IdentifierTag nodes...\n"; + size_t nSize = m_identifierTags.size(); + m_memMapIdentifierTags.reserve( + nSize * 2); // TODO: check if *2 is good or redundant... + for (unsigned int ii = 0; ii < nSize; ++ii) { + // const unsigned int nodeID = std::stoi(m_identifierTags[ii][0]); + // // RMB: not used at the moment, commented to avoid warnings + const int identifier = std::stoi(m_identifierTags[ii][1]); + GeoIdentifierTag* nodePtr = new GeoIdentifierTag(identifier); + storeBuiltIdentifierTag(nodePtr); + } + if (nSize > 0) + std::cout << "All " << nSize << " SerialIdentifiers have been built!\n"; +} + +//! Iterate over the list of NameTag nodes, build them all, and store their +//! pointers +void ReadGeoModel::buildAllNameTags() { + if (m_loglevel >= 1) std::cout << "Building all NameTag nodes...\n"; + size_t nSize = m_nameTags.size(); + m_memMapNameTags.reserve(nSize * + 2); // TODO: check if *2 is good or redundant... + for (unsigned int ii = 0; ii < nSize; ++ii) { + // const unsigned int nodeID = std::stoi(m_nameTags[ii][0]); // RMB: + // not used at teh moment, commented to avoid warnings + const std::string baseName = m_nameTags[ii][1]; + GeoNameTag* nodePtr = new GeoNameTag(baseName); + storeBuiltNameTag(nodePtr); + } + if (nSize > 0) + std::cout << "All " << nSize << " NameTags have been built!\n"; } - -//! Iterate over the list of NameTag nodes, build them all, and store their pointers -void ReadGeoModel::buildAllNameTags() -{ - if (m_debug) std::cout << "Building all NameTag nodes...\n"; - size_t nSize = m_nameTags.size(); - m_memMapNameTags.reserve( nSize*2 ); // TODO: check if *2 is good or redundant... - for (unsigned int ii=0; ii<nSize; ++ii) { - //const unsigned int nodeID = std::stoi(m_nameTags[ii][0]); // RMB: not used at teh moment, commented to avoid warnings - const std::string baseName = m_nameTags[ii][1]; - GeoNameTag* nodePtr = new GeoNameTag(baseName); - storeBuiltNameTag(nodePtr); - } - if (nSize>0) std::cout << "All " << nSize << " NameTags have been built!\n"; +//! Iterate over the list of nodes, build them all, and store their pointers +void ReadGeoModel::buildAllElements() { + if (m_loglevel >= 1) std::cout << "Building all Elements...\n"; + size_t nSize = m_elements.size(); + m_memMapElements.reserve(nSize * + 2); // TODO: check if *2 is good or redundant... + for (unsigned int ii = 0; ii < nSize; ++ii) { + const unsigned int nodeID = std::stoi(m_elements[ii][0]); + buildElement(nodeID); // nodes' IDs start from 1 + } + if (nSize > 0) + std::cout << "All " << nSize << " Elements have been built!\n"; } //! Iterate over the list of nodes, build them all, and store their pointers -void ReadGeoModel::buildAllElements() -{ - if (m_debug) std::cout << "Building all Elements...\n"; - size_t nSize = m_elements.size(); - m_memMapElements.reserve( nSize*2 ); // TODO: check if *2 is good or redundant... - for (unsigned int ii=0; ii<nSize; ++ii) { - const unsigned int nodeID = std::stoi(m_elements[ii][0]); - buildElement(nodeID); // nodes' IDs start from 1 - } - if (nSize>0) std::cout << "All " << nSize << " Elements have been built!\n"; +void ReadGeoModel::buildAllMaterials() { + if (m_loglevel >= 1) std::cout << "Building all Materials...\n"; + size_t nSize = m_materials.size(); + m_memMapMaterials.reserve(nSize * + 2); // TODO: check if *2 is good or redundant... + for (unsigned int ii = 0; ii < nSize; ++ii) { + const unsigned int nodeID = std::stoi(m_materials[ii][0]); + buildMaterial(nodeID); // nodes' IDs start from 1 + } + if (nSize > 0) + std::cout << "All " << nSize << " Materials have been built!\n"; } //! Iterate over the list of nodes, build them all, and store their pointers -void ReadGeoModel::buildAllMaterials() -{ - if (m_debug) std::cout << "Building all Materials...\n"; - size_t nSize = m_materials.size(); - m_memMapMaterials.reserve( nSize*2 ); // TODO: check if *2 is good or redundant... - for (unsigned int ii=0; ii<nSize; ++ii) { - const unsigned int nodeID = std::stoi(m_materials[ii][0]); - buildMaterial(nodeID); // nodes' IDs start from 1 - } - if (nSize>0) std::cout << "All " << nSize << " Materials have been built!\n"; +void ReadGeoModel::buildAllLogVols() { + if (m_loglevel >= 1) std::cout << "Building all LogVols...\n"; + size_t nSize = m_logVols.size(); + m_memMapLogVols.reserve(nSize * + 2); // TODO: check if *2 is good or redundant... + for (unsigned int ii = 0; ii < nSize; ++ii) { + const unsigned int nodeID = std::stoi(m_logVols[ii][0]); + buildLogVol(nodeID); + } + if (nSize > 0) + std::cout << "All " << nSize << " LogVols have been built!\n"; } -//! Iterate over the list of nodes, build them all, and store their pointers -void ReadGeoModel::buildAllLogVols() -{ - if (m_debug) std::cout << "Building all LogVols...\n"; - size_t nSize = m_logVols.size(); - m_memMapLogVols.reserve( nSize*2 ); // TODO: check if *2 is good or redundant... - for (unsigned int ii=0; ii<nSize; ++ii) { - const unsigned int nodeID = std::stoi(m_logVols[ii][0]); - buildLogVol(nodeID); - } - if (nSize>0) std::cout << "All " << nSize << " LogVols have been built!\n"; -} - - //// FIXME: TODO: move to an utility class -//void printQHashQstringUInt(QHash<QString, unsigned int> qq) { -// QHash<QString, unsigned int>::const_iterator i = qq.constBegin(); -// while (i != qq.constEnd()) { -// std::cout << i.key().toStdString() << ": " << i.value() << std::endl; -// } -//} +//// FIXME: TODO: move to an utility class +// void printQHashQstringUInt(QHash<QString, unsigned int> qq) { +// QHash<QString, unsigned int>::const_iterator i = qq.constBegin(); +// while (i != qq.constEnd()) { +// std::cout << i.key().toStdString() << ": " << i.value() << std::endl; +// } +// } //! Iterate over the list of nodes, build them all, and store their pointers -void ReadGeoModel::buildAllPhysVols() -{ - if (m_debug) std::cout << "Building all PhysVols...\n"; - if (m_physVols.size() == 0) { - std::cout << "ERROR!!! No input PhysVols found! Exiting..." << std::endl; - exit(EXIT_FAILURE); - } - const unsigned int tableID = m_tableName_toTableID["GeoPhysVol"]; - size_t nSize = m_physVols.size(); - m_memMapPhysVols.reserve( nSize*2 ); // TODO: check if *2 is good or redundant... - for (unsigned int ii=0; ii<nSize; ++ii) { - const unsigned int volID = std::stoi(m_physVols[ii][0]); - const unsigned int logVolID = std::stoi(m_physVols[ii][1]); - // std::cout << "building PhysVol n. " << volID << " (logVol: " << logVolID << ")" << std::endl; - buildVPhysVol(volID, tableID, logVolID); - } - if (nSize>0) std::cout << "All " << nSize << " PhysVols have been built!\n"; +void ReadGeoModel::buildAllPhysVols() { + if (m_debug) std::cout << "Building all PhysVols...\n"; + if (m_physVols.size() == 0) { + std::cout << "ERROR!!! No input PhysVols found! Exiting..." + << std::endl; + exit(EXIT_FAILURE); + } + const unsigned int tableID = m_tableName_toTableID["GeoPhysVol"]; + size_t nSize = m_physVols.size(); + m_memMapPhysVols.reserve(nSize * + 2); // TODO: check if *2 is good or redundant... + for (unsigned int ii = 0; ii < nSize; ++ii) { + const unsigned int volID = std::stoi(m_physVols[ii][0]); + const unsigned int logVolID = std::stoi(m_physVols[ii][1]); + // std::cout << "building PhysVol n. " << volID << " (logVol: " << + // logVolID << ")" << std::endl; + buildVPhysVol(volID, tableID, logVolID); + } + if (nSize > 0) + std::cout << "All " << nSize << " PhysVols have been built!\n"; } //! Iterate over the list of nodes, build them all, and store their pointers -void ReadGeoModel::buildAllFullPhysVols() -{ - if (m_debug) std::cout << "Building all FullPhysVols...\n"; - const unsigned int tableID = m_tableName_toTableID["GeoFullPhysVol"]; - size_t nSize = m_fullPhysVols.size(); - m_memMapFullPhysVols.reserve( nSize*2 ); // TODO: check if *2 is good or redundant... - for (unsigned int ii=0; ii<nSize; ++ii) { - const unsigned int volID = std::stoi(m_fullPhysVols[ii][0]); - const unsigned int logVolID = std::stoi(m_fullPhysVols[ii][1]); - // std::cout << "building PhysVol n. " << volID << " (logVol: " << logVolID << ")" << std::endl; - buildVPhysVol(volID, tableID, logVolID); - } - if (nSize>0) std::cout << "All " << nSize << " FullPhysVols have been built!\n"; -} - -//! Iterate over the list of GeoAlignableTransforms nodes, build them all, and store their pointers -void ReadGeoModel::buildAllAlignableTransforms() -{ - if (m_debug) std::cout << "Building all AlignableTransforms...\n"; - size_t nSize = m_alignableTransforms.size(); - m_memMapAlignableTransforms.reserve( nSize*2 ); // TODO: check if *2 is good or redundant... - for (unsigned int ii=0; ii<nSize; ++ii) { - const unsigned int volID = std::stoi(m_alignableTransforms[ii][0]); - buildAlignableTransform(volID); - } - if (nSize>0) std::cout << "All " << nSize << " AlignableTransforms have been built!\n"; -} - -//! Iterate over the list of GeoTransforms nodes, build them all, and store their pointers -void ReadGeoModel::buildAllTransforms() -{ - if (m_debug) std::cout << "Building all Transforms...\n"; - size_t nSize = m_transforms.size(); - m_memMapTransforms.reserve( nSize*2 ); // TODO: check if *2 is good or redundant... - for (unsigned int ii=0; ii<nSize; ++ii) { - const unsigned int volID = std::stoi(m_transforms[ii][0]); - buildTransform(volID); - } - if (nSize>0) std::cout << "All " << nSize << " Transforms have been built!\n"; -} - -//! Iterate over the list of GeoTransforms nodes, build them all, and store their pointers -void ReadGeoModel::buildAllSerialTransformers() -{ - if (m_debug) std::cout << "Building all SerialTransformers...\n"; - size_t nSize = m_serialTransformers.size(); - m_memMapSerialTransformers.reserve( nSize*2 ); // TODO: check if 2 is good or redundant... - for (unsigned int ii=0; ii<nSize; ++ii) { - const unsigned int volID = std::stoi(m_serialTransformers[ii][0]); - buildSerialTransformer(volID); - } - if (nSize>0) std::cout << "All " << nSize << " SerialTransformers have been built!\n"; +void ReadGeoModel::buildAllFullPhysVols() { + if (m_debug) std::cout << "Building all FullPhysVols...\n"; + const unsigned int tableID = m_tableName_toTableID["GeoFullPhysVol"]; + size_t nSize = m_fullPhysVols.size(); + m_memMapFullPhysVols.reserve( + nSize * 2); // TODO: check if *2 is good or redundant... + for (unsigned int ii = 0; ii < nSize; ++ii) { + const unsigned int volID = std::stoi(m_fullPhysVols[ii][0]); + const unsigned int logVolID = std::stoi(m_fullPhysVols[ii][1]); + // std::cout << "building PhysVol n. " << volID << " (logVol: " << + // logVolID << ")" << std::endl; + buildVPhysVol(volID, tableID, logVolID); + } + if (nSize > 0) + std::cout << "All " << nSize << " FullPhysVols have been built!\n"; +} + +//! Iterate over the list of GeoAlignableTransforms nodes, build them all, and +//! store their pointers +void ReadGeoModel::buildAllAlignableTransforms() { + if (m_debug) std::cout << "Building all AlignableTransforms...\n"; + size_t nSize = m_alignableTransforms.size(); + m_memMapAlignableTransforms.reserve( + nSize * 2); // TODO: check if *2 is good or redundant... + for (unsigned int ii = 0; ii < nSize; ++ii) { + const unsigned int volID = std::stoi(m_alignableTransforms[ii][0]); + buildAlignableTransform(volID); + } + if (nSize > 0) + std::cout << "All " << nSize + << " AlignableTransforms have been built!\n"; +} + +//! Iterate over the list of GeoTransforms nodes, build them all, and store +//! their pointers +void ReadGeoModel::buildAllTransforms() { + if (m_debug) std::cout << "Building all Transforms...\n"; + size_t nSize = m_transforms.size(); + m_memMapTransforms.reserve(nSize * + 2); // TODO: check if *2 is good or redundant... + for (unsigned int ii = 0; ii < nSize; ++ii) { + const unsigned int volID = std::stoi(m_transforms[ii][0]); + buildTransform(volID); + } + if (nSize > 0) + std::cout << "All " << nSize << " Transforms have been built!\n"; +} + +//! Iterate over the list of GeoTransforms nodes, build them all, and store +//! their pointers +void ReadGeoModel::buildAllSerialTransformers() { + if (m_debug) std::cout << "Building all SerialTransformers...\n"; + size_t nSize = m_serialTransformers.size(); + m_memMapSerialTransformers.reserve( + nSize * 2); // TODO: check if 2 is good or redundant... + for (unsigned int ii = 0; ii < nSize; ++ii) { + const unsigned int volID = std::stoi(m_serialTransformers[ii][0]); + buildSerialTransformer(volID); + } + if (nSize > 0) + std::cout << "All " << nSize + << " SerialTransformers have been built!\n"; } - // FIXME: implement build function and cache for Functions +// FIXME: implement build function and cache for Functions // //! Iterate over the list of nodes, build them all, and store their pointers // void ReadGeoModel::buildAllFunctions() // { // if (m_debug) std::cout << "Building all Functions...\n"; //// if (m_serialTransformers.size() == 0) { -//// std::cout << "ERROR!!! input SerialTransformers are empty! Exiting..." << std::endl; -//// exit(EXIT_FAILURE); -//// } -//// size_t nSize = m_functions.size(); -//// m_memMapFunctions.reserve( nSize*2 ); // TODO: check if 2 is good or redundant... -//// for (unsigned int ii=0; ii<nSize; ++ii) { -//// buildFunction(ii+1); // nodes' IDs start from 1 -//// } -// QHash<unsigned int, QStringList>::const_iterator i = m_functions.constBegin(); -// while (i != m_functions.constEnd()) { +//// std::cout << "ERROR!!! input SerialTransformers are empty! Exiting..." +///<< std::endl; / exit(EXIT_FAILURE); / } / size_t nSize = +/// m_functions.size(); / m_memMapFunctions.reserve( nSize*2 ); // TODO: check +/// if 2 is good or redundant... / for (unsigned int ii=0; ii<nSize; ++ii) { / +/// buildFunction(ii+1); // nodes' IDs start from 1 / } +// QHash<unsigned int, QStringList>::const_iterator i = +// m_functions.constBegin(); while (i != m_functions.constEnd()) { // unsigned int id = i.key(); // buildFunction(id); // ++i; // } -// std::cout << "All Functions have been built!\n"; // } +/* +//! Iterate over the list of nodes, build them all, and store their pointers +void ReadGeoModel::buildAllPhysVols() { + if (m_loglevel >= 1) std::cout << "Building all PhysVols...\n"; + if (m_physVols.size() == 0) { + std::cout << "ERROR!!! No input PhysVols found! Exiting..." + << std::endl; + exit(EXIT_FAILURE); + } + const unsigned int tableID = m_tableName_toTableID["GeoPhysVol"]; + size_t nSize = m_physVols.size(); + m_memMapPhysVols.reserve(nSize * + 2); // TODO: check if *2 is good or redundant... + for (unsigned int ii = 0; ii < nSize; ++ii) { + const unsigned int volID = std::stoi(m_physVols[ii][0]); + const unsigned int logVolID = std::stoi(m_physVols[ii][1]); + // std::cout << "building PhysVol n. " << volID << " (logVol: " << + // logVolID << ")" << std::endl; + buildVPhysVol(volID, tableID, logVolID); + } + if (nSize > 0) + std::cout << "All " << nSize << " PhysVols have been built!\n"; +} +//! Iterate over the list of nodes, build them all, and store their pointers +void ReadGeoModel::buildAllFullPhysVols() { + if (m_loglevel >= 1) std::cout << "Building all FullPhysVols...\n"; + const unsigned int tableID = m_tableName_toTableID["GeoFullPhysVol"]; + size_t nSize = m_fullPhysVols.size(); + m_memMapFullPhysVols.reserve( + nSize * 2); // TODO: check if *2 is good or redundant... + for (unsigned int ii = 0; ii < nSize; ++ii) { + const unsigned int volID = std::stoi(m_fullPhysVols[ii][0]); + const unsigned int logVolID = std::stoi(m_fullPhysVols[ii][1]); + // std::cout << "building PhysVol n. " << volID << " (logVol: " << + // logVolID << ")" << std::endl; + buildVPhysVol(volID, tableID, logVolID); + } + if (nSize > 0) + std::cout << "All " << nSize << " FullPhysVols have been built!\n"; +} + +//! Iterate over the list of GeoAlignableTransforms nodes, build them all, +//! and store their pointers +void ReadGeoModel::buildAllAlignableTransforms() { + if (m_loglevel >= 1) std::cout << "Building all AlignableTransforms...\n"; + size_t nSize = m_alignableTransforms.size(); + m_memMapAlignableTransforms.reserve( + nSize * 2); // TODO: check if *2 is good or redundant... + for (unsigned int ii = 0; ii < nSize; ++ii) { + const unsigned int volID = std::stoi(m_alignableTransforms[ii][0]); + buildAlignableTransform(volID); + } + if (nSize > 0) + std::cout << "All " << nSize + << " AlignableTransforms have been built!\n"; +} + +//! Iterate over the list of GeoTransforms nodes, build them all, and store +//! their pointers +void ReadGeoModel::buildAllTransforms() { + if (m_loglevel >= 1) std::cout << "Building all Transforms...\n"; + size_t nSize = m_transforms.size(); + m_memMapTransforms.reserve(nSize * + 2); // TODO: check if *2 is good or redundant... + for (unsigned int ii = 0; ii < nSize; ++ii) { + const unsigned int volID = std::stoi(m_transforms[ii][0]); + buildTransform(volID); + } + if (nSize > 0) + std::cout << "All " << nSize << " Transforms have been built!\n"; +} + +//! Iterate over the list of GeoTransforms nodes, build them all, and store +//! their pointers +void ReadGeoModel::buildAllSerialTransformers() { + if (m_loglevel >= 1) std::cout << "Building all SerialTransformers...\n"; + size_t nSize = m_serialTransformers.size(); + m_memMapSerialTransformers.reserve( + nSize * 2); // TODO: check if 2 is good or redundant... + for (unsigned int ii = 0; ii < nSize; ++ii) { + const unsigned int volID = std::stoi(m_serialTransformers[ii][0]); + buildSerialTransformer(volID); + } + if (nSize > 0) + std::cout << "All " << nSize + << " SerialTransformers have been built!\n"; +} +*/ -void ReadGeoModel::loopOverAllChildrenInBunches() -{ + +// FIXME: implement build function and cache for Functions +// //! Iterate over the list of nodes, build them all, and store their +// pointers +/* +void ReadGeoModel::buildAllFunctions() { + if (m_loglevel >= 1) std::cout << "Building all Functions...\n"; + //// if (m_serialTransformers.size() == 0) { + //// std::cout << "ERROR!!! input SerialTransformers are empty! + /// Exiting..." + ///<< std::endl; / exit(EXIT_FAILURE); / } + size_t nSize = m_functions.size(); + m_memMapFunctions.reserve(nSize * + 2); // TODO: check if 2 is good or redundant... + for (unsigned int ii = 0; ii < nSize; ++ii) { + buildFunction(ii + 1); // nodes' IDs start from 1 + } + if (nSize > 0) + std::cout << "All " << nSize << " Functions have been built!\n"; +} +*/ + + + +void ReadGeoModel::loopOverAllChildrenInBunches() { int nChildrenRecords = m_allchildren.size(); - if (m_debug) std::cout << "number of children to process: " << nChildrenRecords << std::endl; + if (m_loglevel >= 1) + std::cout << "number of children to process: " << nChildrenRecords + << std::endl; // If we have a few children, then process them serially - // std::cout << "Running concurrently? " << m_runMultithreaded << std::endl; - if (true) // !(m_runMultithreaded) || nChildrenRecords <= 500) // TODO: test if you can optimize, then revert to if()...else() + // std::cout << "Running concurrently? " << m_runMultithreaded << + // std::endl; + if (true) // !(m_runMultithreaded) || nChildrenRecords <= 500) // TODO: + // test if you can optimize, then revert to if()...else() { - // std::cout << "Running serially...\n"; - loopOverAllChildrenRecords(m_allchildren); + // std::cout << "Running serially...\n"; + loopOverAllChildrenRecords(m_allchildren); } - // ...otherwise, let's spawn some threads to process them in bunches, parallelly! + // ...otherwise, let's spawn some threads to process them in bunches, + // parallelly! else { + // std::cout << "Running concurrently...\n"; - // std::cout << "Running concurrently...\n"; - - std::chrono::system_clock::time_point start, end; - if (m_timing || m_debug || m_deepDebug) { - // Get Start Time - start = std::chrono::system_clock::now(); - } - - // set number of worker threads - unsigned int nThreads = 0; - if(m_runMultithreaded_nThreads > 0) { - nThreads = m_runMultithreaded_nThreads; - } - else if (m_runMultithreaded_nThreads == -1) { - unsigned int nThreadsPlatform = std::thread::hardware_concurrency(); - nThreads = nThreadsPlatform; - if (m_debug || m_deepDebug) std::cout << "INFO - You have asked for hardware native parellelism. On this platform, " << nThreadsPlatform << " concurrent threads are supported. Thus, using " << nThreads << " threads.\n"; - } - - unsigned int nBunches = nChildrenRecords / nThreads; - if (m_debug || m_deepDebug) std::cout << "Processing " << nThreads << " bunches, with " << nBunches << " children each, plus the remainder." << std::endl; - - // a vector to store the "futures" of async calls - std::vector<std::future<void>> futures; - - for (unsigned int bb=0; bb<nThreads; ++bb ) { - - std::vector<std::vector<std::string>> bunch; - - unsigned int start = nBunches * bb; - int len = nBunches; - const unsigned int stop = start + len; - std::vector<std::vector<std::string>>::const_iterator first = m_allchildren.begin() + start; - std::vector<std::vector<std::string>>::const_iterator last = m_allchildren.begin() + stop; - std::vector<std::vector<std::string>>::const_iterator end = m_allchildren.end(); - if ( bb == (nThreads - 1) ) { // last bunch - bunch = std::vector<std::vector<std::string>>(first, end); - } - else { // all bunches but last one - bunch = std::vector<std::vector<std::string>>(first, last); + std::chrono::system_clock::time_point start, end; + if (m_timing || (m_loglevel >= 1)) { + // Get Start Time + start = std::chrono::system_clock::now(); } - if (m_debug || m_deepDebug) { - muxCout.lock(); - std::cout << "Thread " << bb+1 << " - Start: " << start << ", len: " << len << " ['len=-1' = all remaining items]" << std::endl; - muxCout.unlock(); + // set number of worker threads + unsigned int nThreads = 0; + if (m_runMultithreaded_nThreads > 0) { + nThreads = m_runMultithreaded_nThreads; + } else if (m_runMultithreaded_nThreads == -1) { + unsigned int nThreadsPlatform = std::thread::hardware_concurrency(); + nThreads = nThreadsPlatform; + if (m_loglevel >= 1) + std::cout << "INFO - You have asked for hardware native " + "parellelism. On this platform, " + << nThreadsPlatform + << " concurrent threads are supported. Thus, using " + << nThreads << " threads.\n"; } + unsigned int nBunches = nChildrenRecords / nThreads; + if (m_loglevel >= 1) + std::cout << "Processing " << nThreads << " bunches, with " + << nBunches << " children each, plus the remainder." + << std::endl; + + // a vector to store the "futures" of async calls + std::vector<std::future<void>> futures; + + for (unsigned int bb = 0; bb < nThreads; ++bb) { + std::vector<std::vector<std::string>> bunch; + + unsigned int start = nBunches * bb; + int len = nBunches; + const unsigned int stop = start + len; + std::vector<std::vector<std::string>>::const_iterator first = + m_allchildren.begin() + start; + std::vector<std::vector<std::string>>::const_iterator last = + m_allchildren.begin() + stop; + std::vector<std::vector<std::string>>::const_iterator end = + m_allchildren.end(); + if (bb == (nThreads - 1)) { // last bunch + bunch = std::vector<std::vector<std::string>>(first, end); + } else { // all bunches but last one + bunch = std::vector<std::vector<std::string>>(first, last); + } - if (m_debug || m_deepDebug) { - muxCout.lock(); - std::cout << "'bunch' size: " << bunch.size() << std::endl; - muxCout.unlock(); - } + if (m_loglevel >= 1) { + muxCout.lock(); + std::cout << "Thread " << bb + 1 << " - Start: " << start + << ", len: " << len + << " ['len=-1' = all remaining items]" << std::endl; + muxCout.unlock(); + } - futures.push_back( std::async(std::launch::async, &ReadGeoModel::loopOverAllChildrenRecords, this, bunch) ); - } + if (m_loglevel >= 1) { + muxCout.lock(); + std::cout << "'bunch' size: " << bunch.size() << std::endl; + muxCout.unlock(); + } - // wait for all async calls to complete - //retrieve and print the value stored in the 'std::future' - if (m_debug || m_deepDebug) std::cout << "Waiting for the threads to finish...\n" << std::flush; - for(auto &e : futures) { - e.wait(); - } - if (m_debug || m_deepDebug) std::cout << "Done!\n"; + futures.push_back(std::async( + std::launch::async, &ReadGeoModel::loopOverAllChildrenRecords, + this, bunch)); + } - if (m_timing || m_debug || m_deepDebug) { - // Get End Time - end = std::chrono::system_clock::now(); - auto diff = std::chrono::duration_cast < std::chrono::seconds > (end - start).count(); - std::cout << "(Total time taken to recreate all " << nChildrenRecords << " mother-children relationships: " << diff << " seconds)" << std::endl; - } + // wait for all async calls to complete + // retrieve and print the value stored in the 'std::future' + if (m_loglevel >= 1) + std::cout << "Waiting for the threads to finish...\n" << std::flush; + for (auto& e : futures) { + e.wait(); + } + if (m_loglevel >= 1) std::cout << "Done!\n"; + + if (m_timing || (m_loglevel >= 1)) { + // Get End Time + end = std::chrono::system_clock::now(); + auto diff = + std::chrono::duration_cast<std::chrono::seconds>(end - start) + .count(); + std::cout << "(Total time taken to recreate all " + << nChildrenRecords + << " mother-children relationships: " << diff + << " seconds)" << std::endl; + } } return; - } +} - void ReadGeoModel::processParentChild(const std::vector<std::string> &parentchild) - { - if (m_deepDebug) { - muxCout.lock(); - std::cout << "\nReadGeoModel::processParentChild()..." << std::endl; - for (auto& rec : parentchild) std::cout << rec << "-"; - std::cout << std::endl; - muxCout.unlock(); - } +void ReadGeoModel::processParentChild( + const std::vector<std::string>& parentchild) { + if (m_loglevel >= 2) { + muxCout.lock(); + std::cout << "\nReadGeoModel::processParentChild()..." << std::endl; + for (auto& rec : parentchild) std::cout << rec << "-"; + std::cout << std::endl; + muxCout.unlock(); + } // safety check if (parentchild.size() < 8) { - std::cout << "ERROR!!! Probably you are using an old geometry file. Please, get a new one. Exiting..." << std::endl; - exit(EXIT_FAILURE); + std::cout << "ERROR!!! Probably you are using an old geometry file. " + "Please, get a new one. Exiting..." + << std::endl; + exit(EXIT_FAILURE); } // get the parent's details @@ -688,1196 +898,1323 @@ void ReadGeoModel::loopOverAllChildrenInBunches() const unsigned int parentCopyN = std::stoi(parentchild[3]); // get the child's position in the parent's children list - //const unsigned int position = std::stoi(parentchild[4]); // unused + // const unsigned int position = std::stoi(parentchild[4]); // unused // get the child's details const unsigned int childTableId = std::stoi(parentchild[5]); const unsigned int childId = std::stoi(parentchild[6]); const unsigned int childCopyN = std::stoi(parentchild[7]); -// std::string childNodeType = m_tableID_toTableName[childTableId].toStdString(); + // std::string childNodeType = + // m_tableID_toTableName[childTableId].toStdString(); std::string childNodeType = m_tableID_toTableName[childTableId]; - if ( "" == childNodeType || 0 == childNodeType.size()) { - std::cout << "ReadGeoModel -- ERROR!!! childNodeType is empty!!! Aborting..." << std::endl; - exit(EXIT_FAILURE); + if ("" == childNodeType || 0 == childNodeType.size()) { + std::cout << "ReadGeoModel -- ERROR!!! childNodeType is empty!!! " + "Aborting..." + << std::endl; + exit(EXIT_FAILURE); } GeoVPhysVol* parentVol = nullptr; // build or get parent volume. - // Using the parentCopyNumber here, to get a given instance of the parent volume - if (m_deepDebug) { muxCout.lock(); std::cout << "build/get parent volume...\n"; muxCout.unlock(); } - parentVol = dynamic_cast<GeoVPhysVol*>( buildVPhysVolInstance(parentId, parentTableId, parentCopyN) ); + // Using the parentCopyNumber here, to get a given instance of the + // parent volume + if (m_loglevel >= 2) { + muxCout.lock(); + std::cout << "build/get parent volume...\n"; + muxCout.unlock(); + } + parentVol = dynamic_cast<GeoVPhysVol*>( + buildVPhysVolInstance(parentId, parentTableId, parentCopyN)); std::string parentName = parentVol->getLogVol()->getName(); - if (childNodeType == "GeoPhysVol") { - GeoPhysVol* childNode = dynamic_cast<GeoPhysVol*>(buildVPhysVolInstance(childId, childTableId, childCopyN)); - volAddHelper(parentVol, childNode); - } - else if (childNodeType == "GeoFullPhysVol") { - GeoFullPhysVol* childNode = dynamic_cast<GeoFullPhysVol*>(buildVPhysVolInstance(childId, childTableId, childCopyN)); - volAddHelper(parentVol, childNode); - } - else if (childNodeType == "GeoSerialDenominator") { - GeoSerialDenominator* childNode = getBuiltSerialDenominator(childId); - volAddHelper(parentVol, childNode); - } - else if (childNodeType == "GeoSerialIdentifier") { - GeoSerialIdentifier* childNode = getBuiltSerialIdentifier(childId); - volAddHelper(parentVol, childNode); - } - else if (childNodeType == "GeoIdentifierTag") { - GeoIdentifierTag* childNode = getBuiltIdentifierTag(childId); - volAddHelper(parentVol, childNode); - } - else if (childNodeType == "GeoAlignableTransform") { - GeoAlignableTransform* childNode = getBuiltAlignableTransform(childId); - volAddHelper(parentVol, childNode); - } - else if (childNodeType == "GeoTransform") { - if (m_deepDebug) { muxCout.lock(); std::cout << "get transform child...\n"; muxCout.unlock(); } - GeoTransform* childNode = getBuiltTransform(childId); - volAddHelper(parentVol, childNode); - } - else if (childNodeType == "GeoSerialTransformer") { - GeoSerialTransformer* childNode = getBuiltSerialTransformer(childId); - volAddHelper(parentVol, childNode); - } - else if (childNodeType == "GeoNameTag") { - GeoNameTag* childNode = getBuiltNameTag(childId); - volAddHelper(parentVol, childNode); - } - else { - std::cout << "[" << childNodeType << "] ==> ERROR!!! - The conversion for this type of child node needs to be implemented." << std::endl; - exit(EXIT_FAILURE); - } -} - -void ReadGeoModel::volAddHelper(GeoVPhysVol* vol, GeoGraphNode* volChild) -{ - checkNodePtr(vol, "vol", __func__, __PRETTY_FUNCTION__); - checkNodePtr(volChild, "volChild", __func__, __PRETTY_FUNCTION__); - if (dynamic_cast<GeoPhysVol*>(vol)) { - GeoPhysVol* volume = dynamic_cast<GeoPhysVol*>(vol); - volume->add(volChild); - } else if (dynamic_cast<GeoFullPhysVol*>(vol)) { - GeoFullPhysVol* volume = dynamic_cast<GeoFullPhysVol*>(vol); - volume->add(volChild); - } -} - -//TODO: to be moved to an utility class -void ReadGeoModel::checkNodePtr(GeoGraphNode* nodePtr, std::string varName, std::string funcName, std::string funcSignature) -{ - if (!nodePtr) { - muxCout.lock(); - std::cout << "ERROR! A pointer to a GeoGraphNode instance is NULL {"<<varName<<" "<<funcName<<" "<<"["<<funcSignature<<"]}. Exiting..." << std::endl; - exit(EXIT_FAILURE); - muxCout.unlock(); - } + if (childNodeType == "GeoPhysVol") { + GeoPhysVol* childNode = dynamic_cast<GeoPhysVol*>( + buildVPhysVolInstance(childId, childTableId, childCopyN)); + volAddHelper(parentVol, childNode); + } else if (childNodeType == "GeoFullPhysVol") { + GeoFullPhysVol* childNode = dynamic_cast<GeoFullPhysVol*>( + buildVPhysVolInstance(childId, childTableId, childCopyN)); + volAddHelper(parentVol, childNode); + } else if (childNodeType == "GeoSerialDenominator") { + GeoSerialDenominator* childNode = getBuiltSerialDenominator(childId); + volAddHelper(parentVol, childNode); + } else if (childNodeType == "GeoSerialIdentifier") { + GeoSerialIdentifier* childNode = getBuiltSerialIdentifier(childId); + volAddHelper(parentVol, childNode); + } else if (childNodeType == "GeoIdentifierTag") { + GeoIdentifierTag* childNode = getBuiltIdentifierTag(childId); + volAddHelper(parentVol, childNode); + } else if (childNodeType == "GeoAlignableTransform") { + GeoAlignableTransform* childNode = getBuiltAlignableTransform(childId); + volAddHelper(parentVol, childNode); + } else if (childNodeType == "GeoTransform") { + if (m_loglevel >= 2) { + muxCout.lock(); + std::cout << "get transform child...\n"; + muxCout.unlock(); + } + GeoTransform* childNode = getBuiltTransform(childId); + volAddHelper(parentVol, childNode); + } else if (childNodeType == "GeoSerialTransformer") { + GeoSerialTransformer* childNode = getBuiltSerialTransformer(childId); + volAddHelper(parentVol, childNode); + } else if (childNodeType == "GeoNameTag") { + GeoNameTag* childNode = getBuiltNameTag(childId); + volAddHelper(parentVol, childNode); + } else { + std::cout << "[" << childNodeType + << "] ==> ERROR!!! - The conversion for this type of child " + "node needs to be implemented." + << std::endl; + exit(EXIT_FAILURE); + } } - // TODO: move it to an utility class -//void ReadGeoModel::checkInputString(QString input) -//{ -// if (input.isEmpty() || input.isNull() || input == "NULL") { -// std::cout << "ERROR!!! Input QString is empty or equal to 'NULL'!!! Aborting..." << std::endl; -// exit(1); -// } -//} +void ReadGeoModel::volAddHelper(GeoVPhysVol* vol, GeoGraphNode* volChild) { + checkNodePtr(vol, "vol", __func__, __PRETTY_FUNCTION__); + checkNodePtr(volChild, "volChild", __func__, __PRETTY_FUNCTION__); + if (dynamic_cast<GeoPhysVol*>(vol)) { + GeoPhysVol* volume = dynamic_cast<GeoPhysVol*>(vol); + volume->add(volChild); + } else if (dynamic_cast<GeoFullPhysVol*>(vol)) { + GeoFullPhysVol* volume = dynamic_cast<GeoFullPhysVol*>(vol); + volume->add(volChild); + } +} + +// TODO: to be moved to an utility class +void ReadGeoModel::checkNodePtr(GeoGraphNode* nodePtr, std::string varName, + std::string funcName, + std::string funcSignature) { + if (!nodePtr) { + muxCout.lock(); + std::cout << "ERROR! A pointer to a GeoGraphNode instance is NULL {" + << varName << " " << funcName << " " + << "[" << funcSignature << "]}. Exiting..." << std::endl; + exit(EXIT_FAILURE); + muxCout.unlock(); + } +} +// TODO: move it to an utility class +// void ReadGeoModel::checkInputString(QString input) +//{ +// if (input.isEmpty() || input.isNull() || input == "NULL") { +// std::cout << "ERROR!!! Input QString is empty or equal to 'NULL'!!! +// Aborting..." << std::endl; exit(1); +// } +// } // Instantiate a PhysVol and get its children -GeoVPhysVol* ReadGeoModel::buildVPhysVolInstance(const unsigned int id, const unsigned int tableId, const unsigned int copyN) -{ - if (m_deepDebug) { - muxCout.lock(); - std::cout << "ReadGeoModel::buildVPhysVolInstance() - id: " << id - << ", tableId: " << tableId - << ", copyN: " << copyN << std::endl; - muxCout.unlock(); - } +GeoVPhysVol* ReadGeoModel::buildVPhysVolInstance(const unsigned int id, + const unsigned int tableId, + const unsigned int copyN) { + if (m_loglevel >= 2) { + muxCout.lock(); + std::cout << "ReadGeoModel::buildVPhysVolInstance() - id: " << id + << ", tableId: " << tableId << ", copyN: " << copyN + << std::endl; + muxCout.unlock(); + } // A - if the instance has been previously built, return that - //if ( nullptr != getVPhysVol(id, tableId, copyN)) { - if ( nullptr != getVPhysVol(id, tableId)) { - if (m_deepDebug) { + // if ( nullptr != getVPhysVol(id, tableId, copyN)) { + if (nullptr != getVPhysVol(id, tableId)) { + if (m_loglevel >= 2) { muxCout.lock(); - //std::cout << "getting the instance volume from memory... Returning: [" << getVPhysVol(id, tableId, copyN) << "] -- logvol: " << ((GeoVPhysVol*)getVPhysVol(id, tableId, copyN))->getLogVol()->getName() << std::endl; - std::cout << "getting the instance volume from memory... Returning: [" << getVPhysVol(id, tableId) << "] -- logvol: " << ((GeoVPhysVol*)getVPhysVol(id, tableId))->getLogVol()->getName() << std::endl; + // std::cout << "getting the instance volume from memory... + // Returning: [" << getVPhysVol(id, tableId, copyN) << "] -- + // logvol: " << ((GeoVPhysVol*)getVPhysVol(id, tableId, + // copyN))->getLogVol()->getName() << std::endl; + std::cout + << "getting the instance volume from memory... Returning: [" + << getVPhysVol(id, tableId) << "] -- logvol: " + << ((GeoVPhysVol*)getVPhysVol(id, tableId)) + ->getLogVol() + ->getName() + << std::endl; muxCout.unlock(); } - //return dynamic_cast<GeoVPhysVol*>(getVPhysVol(id, tableId, copyN)); + // return dynamic_cast<GeoVPhysVol*>(getVPhysVol(id, tableId, + // copyN)); return dynamic_cast<GeoVPhysVol*>(getVPhysVol(id, tableId)); } - // B - if not built already, then get the actual volume, - // which should be already built by now, - // get the logVol from it and build a new VPhysVol instance in the heap; - // then, associate a copy number to it, - // and store the new instance into the cache. - GeoVPhysVol* vol = nullptr; - bool volFound = true; - if (1==tableId) { - if(isBuiltPhysVol(id)) { - vol = new GeoPhysVol( getBuiltPhysVol(id)->getLogVol() ); - if (m_deepDebug) { - muxCout.lock(); - std::cout << "PhysVol not instanced yet, building the instance now [" << vol << "] -- logvol: " << vol->getLogVol()->getName() << std::endl; - muxCout.unlock(); - } - } - else - volFound = false; - } - else if (2==tableId) { - if(isBuiltFullPhysVol(id)) - vol = new GeoFullPhysVol( getBuiltFullPhysVol(id)->getLogVol() ); - else - volFound = false; - } - if (!volFound) { - std::cout << "ERROR! VPhysVol not found! It should be already built, by now. Exiting...\n"; - exit(EXIT_FAILURE); - } - //storeVPhysVol(id, tableId, copyN, vol); - storeVPhysVol(id, tableId, vol); - - return vol; -} - -//! Build the actual VPhysVol (GeoPhysVol or GeoFullPhysVol), which will then be used to create -//! instances of that volume by using the `copyNumber`. -//! Here, however, we do not need to specify -//! any copyNumber, because the actual GeoPVPhysVol is the same for all copy instances. -GeoVPhysVol* ReadGeoModel::buildVPhysVol(const unsigned int id, const unsigned int tableId, unsigned int /*defaults to "0"*/ logVol_ID) -{ - - if (m_deepDebug) { muxCout.lock(); std::cout << "ReadGeoModel::buildVPhysVol() - " << id << ", " << tableId << std::endl; muxCout.unlock(); } - - std::string nodeType = m_tableID_toTableName[tableId]; - - bool errorType = false; - - // get the actual VPhysVol volume, if built already - if ( nodeType == "GeoPhysVol" && isBuiltPhysVol(id) ) { - if (m_deepDebug) { muxCout.lock(); std::cout << "getting the actual PhysVol from cache...\n"; ; muxCout.unlock(); } - return getBuiltPhysVol(id); - } else if ( nodeType == "GeoFullPhysVol" && isBuiltFullPhysVol(id)){ - if (m_deepDebug) { muxCout.lock(); std::cout << "getting the actual FullPhysVol from cache...\n"; ; muxCout.unlock(); } - return getBuiltFullPhysVol(id); - } - - // if not built already, then get its parameters and build it now - if (logVol_ID==0) { - // get the volume's parameters - std::vector<std::string> values; - if (nodeType == "GeoPhysVol") - values = m_physVols[id]; - else if (nodeType == "GeoFullPhysVol") - values = m_fullPhysVols[id]; - - logVol_ID = std::stoi(values[1]); - } - - // GET LOGVOL - GeoLogVol* logVol = getBuiltLog(logVol_ID); - if (!logVol) { - std::cout << "ERROR!!! LogVol is NULL!" << std::endl; -// exit(EXIT_FAILURE); - } - if (m_deepDebug) { muxCout.lock(); std::cout << "using the cached LogVol [" << logVol_ID << "] w/ address: " << logVol << "...\n"; ; muxCout.unlock(); } - - // a pointer to the VPhysVol - GeoVPhysVol* vol = nullptr; - - // BUILD THE PHYSVOL OR THE FULLPHYSVOL - if (nodeType == "GeoPhysVol") { - GeoPhysVol* pVol = new GeoPhysVol(logVol); - storeBuiltPhysVol(pVol); - vol = pVol; - } - else if (nodeType == "GeoFullPhysVol") { - GeoFullPhysVol* fpVol = new GeoFullPhysVol(logVol); - storeBuiltFullPhysVol(fpVol); - vol = fpVol; - } - else - errorType = true; - - if (errorType) { - muxCout.lock(); - std::cout << "ERROR! Unkonwn node type. Exiting..." <<std::endl; - muxCout.unlock(); - exit(EXIT_FAILURE); - } + // B - if not built already, then get the actual volume, + // which should be already built by now, + // get the logVol from it and build a new VPhysVol instance in the heap; + // then, associate a copy number to it, + // and store the new instance into the cache. + GeoVPhysVol* vol = nullptr; + bool volFound = true; + if (1 == tableId) { + if (isBuiltPhysVol(id)) { + vol = new GeoPhysVol(getBuiltPhysVol(id)->getLogVol()); + if (m_loglevel >= 2) { + muxCout.lock(); + std::cout + << "PhysVol not instanced yet, building the instance now [" + << vol << "] -- logvol: " << vol->getLogVol()->getName() + << std::endl; + muxCout.unlock(); + } + } else + volFound = false; + } else if (2 == tableId) { + if (isBuiltFullPhysVol(id)) + vol = new GeoFullPhysVol(getBuiltFullPhysVol(id)->getLogVol()); + else + volFound = false; + } else { + std::cerr << "ERROR!! It seems that the 'world' volume is of type other than GeoPhysVol or GeoFullPhysVol, which is forbidden! If you have questions, please send a message to <geomodel-developers@cern.ch>" << std::endl; + exit(EXIT_FAILURE); + } + if (!volFound) { + std::cout << "ERROR! VPhysVol not found! It should be already built, " + "by now. Exiting...\n"; + exit(EXIT_FAILURE); + } + // storeVPhysVol(id, tableId, copyN, vol); + storeVPhysVol(id, tableId, vol); - return vol; + return vol; } +//! Build the actual VPhysVol (GeoPhysVol or GeoFullPhysVol), which will then be +//! used to create instances of that volume by using the `copyNumber`. Here, +//! however, we do not need to specify any copyNumber, because the actual +//! GeoPVPhysVol is the same for all copy instances. +GeoVPhysVol* ReadGeoModel::buildVPhysVol( + const unsigned int id, const unsigned int tableId, + unsigned int /*defaults to "0"*/ logVol_ID) { + if (m_loglevel >= 2) { + muxCout.lock(); + std::cout << "ReadGeoModel::buildVPhysVol() - " << id << ", " << tableId + << std::endl; + muxCout.unlock(); + } + std::string nodeType = m_tableID_toTableName[tableId]; -// Get the root volume -GeoPhysVol* ReadGeoModel::getRootVolume() -{ - if (m_deepDebug) { - muxCout.lock(); - std::cout << "ReadGeoModel::getRootVolume()" << std::endl; - muxCout.unlock(); - } - const unsigned int id = std::stoi(m_root_vol_data[1]); // TODO: GeoModel GetRoot() should return integers instead of strings... - const unsigned int tableId = std::stoi(m_root_vol_data[2]); - const unsigned int copyNumber = 1; // the Root volume has only one copy by definition - GeoPhysVol* root = dynamic_cast<GeoPhysVol*>(buildVPhysVolInstance(id, tableId, copyNumber)); - checkNodePtr(root, "root", __func__, __PRETTY_FUNCTION__); - return root; -} + bool errorType = false; + // get the actual VPhysVol volume, if built already + if (nodeType == "GeoPhysVol" && isBuiltPhysVol(id)) { + if (m_loglevel >= 2) { + muxCout.lock(); + std::cout << "getting the actual PhysVol from cache...\n"; + ; + muxCout.unlock(); + } + return getBuiltPhysVol(id); + } else if (nodeType == "GeoFullPhysVol" && isBuiltFullPhysVol(id)) { + if (m_loglevel >= 2) { + muxCout.lock(); + std::cout << "getting the actual FullPhysVol from cache...\n"; + ; + muxCout.unlock(); + } + return getBuiltFullPhysVol(id); + } -GeoMaterial* ReadGeoModel::buildMaterial(const unsigned int id) -{ - if ( isBuiltMaterial(id) ){ - return getBuiltMaterial(id); - } + // if not built already, then get its parameters and build it now + if (logVol_ID == 0) { + // get the volume's parameters + std::vector<std::string> values; + if (nodeType == "GeoPhysVol") + values = m_physVols[id]; + else if (nodeType == "GeoFullPhysVol") + values = m_fullPhysVols[id]; - if (m_deepDebug) { - muxCout.lock(); - std::cout << "ReadGeoModel::buildMaterial()" << std::endl; - muxCout.unlock(); - } - std::vector<std::string> values = m_materials[id-1]; + logVol_ID = std::stoi(values[1]); + } - const unsigned int matId = std::stoi(values[0]); - const std::string matName = values[1]; - double matDensity = std::stod(values[2]); - std::string matElements = values[3]; + // GET LOGVOL + GeoLogVol* logVol = getBuiltLog(logVol_ID); + if (!logVol) { + std::cout << "ERROR!!! LogVol is NULL!" << std::endl; + // exit(EXIT_FAILURE); + } + if (m_loglevel >= 2) { + muxCout.lock(); + std::cout << "using the cached LogVol [" << logVol_ID + << "] w/ address: " << logVol << "...\n"; + ; + muxCout.unlock(); + } - if (m_deepDebug) { - muxCout.lock(); - std::cout << "\tMaterial - ID:" << matId - << ", name:" << matName - << ", density:" << matDensity - << " ( " << matDensity / (SYSTEM_OF_UNITS::g/SYSTEM_OF_UNITS::cm3) << "[g/cm3] )" - << ", elements:" << matElements; - muxCout.unlock(); - } + // a pointer to the VPhysVol + GeoVPhysVol* vol = nullptr; + + // BUILD THE PHYSVOL OR THE FULLPHYSVOL + if (nodeType == "GeoPhysVol") { + GeoPhysVol* pVol = new GeoPhysVol(logVol); + storeBuiltPhysVol(pVol); + vol = pVol; + } else if (nodeType == "GeoFullPhysVol") { + GeoFullPhysVol* fpVol = new GeoFullPhysVol(logVol); + storeBuiltFullPhysVol(fpVol); + vol = fpVol; + } else + errorType = true; + + if (errorType) { + muxCout.lock(); + std::cout << "ERROR! Unkonwn node type. Exiting..." << std::endl; + muxCout.unlock(); + exit(EXIT_FAILURE); + } - GeoMaterial* mat = new GeoMaterial(matName, matDensity); + return vol; +} - if (matElements.size() > 0) { - // get parameters from DB string - const std::vector<std::string> elements = splitString(matElements, ';'); - for( auto& par : elements) { +// Get the root volume +GeoVPhysVol* ReadGeoModel::getRootVolume() { + if (m_loglevel >= 2) { + muxCout.lock(); + std::cout << "ReadGeoModel::getRootVolume()" << std::endl; + std::cout << "m_root_vol_data: " << m_root_vol_data[0] << ", " << m_root_vol_data[1] << ", " << m_root_vol_data[2] << std::endl; + muxCout.unlock(); + } + const unsigned int id = + std::stoi(m_root_vol_data[1]); // TODO: GeoModel GetRoot() should + // return integers instead of strings... + const std::string tableName = m_root_vol_data[0]; + const unsigned int tableId = m_dbManager->getTableIdFromNodeType(tableName); + const unsigned int copyNumber = + 1; // the Root volume has only one copy by definition + GeoVPhysVol* root = buildVPhysVolInstance(id, tableId, copyNumber); + checkNodePtr(root, "root", __func__, __PRETTY_FUNCTION__); + return root; +} + +GeoMaterial* ReadGeoModel::buildMaterial(const unsigned int id) { + if (isBuiltMaterial(id)) { + return getBuiltMaterial(id); + } - if (m_deepDebug) { - muxCout.lock(); - std::cout << "par: " << par << std::endl; - muxCout.unlock(); + if (m_loglevel >= 2) { + muxCout.lock(); + std::cout << "ReadGeoModel::buildMaterial()" << std::endl; + muxCout.unlock(); + } + std::vector<std::string> values = m_materials[id - 1]; + + const unsigned int matId = std::stoi(values[0]); + const std::string matName = values[1]; + double matDensity = std::stod(values[2]); + std::string matElements = values[3]; + + if (m_loglevel >= 2) { + muxCout.lock(); + std::cout << "\tMaterial - ID:" << matId << ", name:" << matName + << ", density:" << matDensity << " ( " + << matDensity / (SYSTEM_OF_UNITS::g / SYSTEM_OF_UNITS::cm3) + << "[g/cm3] )" + << ", elements:" << matElements; + muxCout.unlock(); + } + + GeoMaterial* mat = new GeoMaterial(matName, matDensity); + + if (matElements.size() > 0) { + // get parameters from DB string + const std::vector<std::string> elements = splitString(matElements, ';'); + for (auto& par : elements) { + if (m_loglevel >= 2) { + muxCout.lock(); + std::cout << "par: " << par << std::endl; + muxCout.unlock(); + } + std::vector<std::string> vars = splitString(par, ':'); + const unsigned int elId = std::stoi(vars[0]); + double elFraction = std::stod(vars[1]); + // GeoElement* el = buildElement(elId); + GeoElement* el = getBuiltElement(elId); + mat->add(el, elFraction); } - std::vector<std::string> vars = splitString(par, ':'); - const unsigned int elId = std::stoi(vars[0]); - double elFraction = std::stod(vars[1]); -// GeoElement* el = buildElement(elId); - GeoElement* el = getBuiltElement(elId); - mat->add(el, elFraction); - } - mat->lock(); - } - storeBuiltMaterial(mat); - return mat; -} - -GeoElement* ReadGeoModel::buildElement(const unsigned int id) -{ - if( isBuiltElement(id) ) { - return getBuiltElement(id); - } + mat->lock(); + } + storeBuiltMaterial(mat); + return mat; +} - if (m_deepDebug) { - muxCout.lock(); - std::cout << "ReadGeoModel::buildElement()" << std::endl; - muxCout.unlock(); - } +GeoElement* ReadGeoModel::buildElement(const unsigned int id) { + if (isBuiltElement(id)) { + return getBuiltElement(id); + } + + if (m_loglevel >= 2) { + muxCout.lock(); + std::cout << "ReadGeoModel::buildElement()" << std::endl; + muxCout.unlock(); + } - if (m_elements.size() == 0) - std::cout << "ERROR! 'm_elements' is empty! Did you load the 'Elements' table? \n\t ==> Aborting...\n" << std::endl; + if (m_elements.size() == 0) + std::cout << "ERROR! 'm_elements' is empty! Did you load the " + "'Elements' table? \n\t ==> Aborting...\n" + << std::endl; - std::vector<std::string> values = m_elements[id-1]; + std::vector<std::string> values = m_elements[id - 1]; - const unsigned int elId = std::stoi(values[0]); - std::string elName = values[1]; - std::string elSymbol = values[2]; - double elZ = std::stod(values[3]); - double elA = std::stod(values[4]); + const unsigned int elId = std::stoi(values[0]); + std::string elName = values[1]; + std::string elSymbol = values[2]; + double elZ = std::stod(values[3]); + double elA = std::stod(values[4]); - if (m_deepDebug) { - muxCout.lock(); - std::cout << "\tElement - ID:" << elId - << ", name:" << elName - << ", symbol:" << elSymbol - << ", Z:" << elZ - << ", A:" << elA - << " ( " << elA / (SYSTEM_OF_UNITS::g/SYSTEM_OF_UNITS::mole) << "[g/mole] )" - << std::endl; - muxCout.unlock(); - } + if (m_loglevel >= 2) { + muxCout.lock(); + std::cout << "\tElement - ID:" << elId << ", name:" << elName + << ", symbol:" << elSymbol << ", Z:" << elZ << ", A:" << elA + << " ( " << elA / (SYSTEM_OF_UNITS::g / SYSTEM_OF_UNITS::mole) + << "[g/mole] )" << std::endl; + muxCout.unlock(); + } - GeoElement* elem = new GeoElement(elName, elSymbol, elZ, elA); - storeBuiltElement(elem); - return elem; + GeoElement* elem = new GeoElement(elName, elSymbol, elZ, elA); + storeBuiltElement(elem); + return elem; } - -std::string ReadGeoModel::getShapeType(const unsigned int shapeId) -{ +std::string ReadGeoModel::getShapeType(const unsigned int shapeId) { if (shapeId > m_shapes.size()) { - std::cout << "ERROR!! Shape ID is larger than the container size. Exiting..." << std::endl; - exit(EXIT_FAILURE); + std::cout + << "ERROR!! Shape ID is larger than the container size. Exiting..." + << std::endl; + exit(EXIT_FAILURE); } - std::vector<std::string> paramsShape = m_shapes[ shapeId-1 ];//remember: shapes' IDs start from 1 - std::string type = paramsShape[1]; - return type; + std::vector<std::string> paramsShape = + m_shapes[shapeId - 1]; // remember: shapes' IDs start from 1 + std::string type = paramsShape[1]; + return type; } +// TODO: move shapes in different files, so code here is more managable +/// Recursive function, to build GeoShape nodes +GeoShape* ReadGeoModel::buildShape(const unsigned int shapeId, + type_shapes_boolean_info* shapes_info_sub) { + if (isBuiltShape(shapeId)) { + return getBuiltShape(shapeId); + } + + if (m_loglevel >= 2) { + muxCout.lock(); + std::cout << "ReadGeoModel::buildShape()" << std::endl; + muxCout.unlock(); + } + + // try // TODO: implement try/catch + // { + std::vector<std::string> paramsShape = + m_shapes[shapeId - 1]; // remember: nodes' IDs start from 1 + // const unsigned int id = std::stoi(paramsShape[0]); // unused + std::string type = paramsShape[1]; + std::string parameters = paramsShape[2]; - //TODO: move shapes in different files, so code here is more managable -/// Recursive function, to build GeoShape nodes -GeoShape* ReadGeoModel::buildShape(const unsigned int shapeId, type_shapes_boolean_info* shapes_info_sub) -{ - if (isBuiltShape(shapeId)) { - return getBuiltShape(shapeId); - } - - if (m_deepDebug) { - muxCout.lock(); - std::cout << "ReadGeoModel::buildShape()" << std::endl; - muxCout.unlock(); - } - -// try // TODO: implement try/catch -// { - std::vector<std::string> paramsShape = m_shapes[ shapeId-1 ]; // remember: nodes' IDs start from 1 - -// const unsigned int id = std::stoi(paramsShape[0]); // unused - std::string type = paramsShape[1]; - std::string parameters = paramsShape[2]; - - // Get shape's parameters from the stored string. - // This will be interpreted differently according to the shape. - std::vector<std::string> shapePars = splitString(parameters, ';'); - - GeoShape* shape = nullptr; - - if (type == "Box") { - // shape parameters - double XHalfLength = 0.; - double YHalfLength = 0.; - double ZHalfLength = 0.; - // get parameters from DB string - for( auto& par : shapePars) { - std::vector<std::string> vars = splitString(par, '='); - std::string varName = vars[0]; - std::string varValue = vars[1]; - if (varName == "XHalfLength") XHalfLength = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "YHalfLength") YHalfLength = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "ZHalfLength") ZHalfLength = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - } - shape = new GeoBox(XHalfLength, YHalfLength, ZHalfLength); - } - else if (type == "Cons") { - // shape parameters - double RMin1 = 0.; - double RMin2 = 0.; - double RMax1 = 0.; - double RMax2 = 0.; - double DZ = 0.; - double SPhi = 0.; - double DPhi = 0.; - // get parameters from DB string - for( auto& par : shapePars) { - std::vector<std::string> vars = splitString(par, '='); - std::string varName = vars[0]; - std::string varValue = vars[1]; - // std::cout << "varValue Cons:" << varValue; - if (varName == "RMin1") RMin1 = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "RMin2") RMin2 = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "RMax1") RMax1 = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "RMax2") RMax2 = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "DZ") DZ = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "SPhi") SPhi = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "DPhi") DPhi = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - } - shape = new GeoCons (RMin1, RMin2, RMax1, RMax2, DZ, SPhi, DPhi); - } - else if (type == "Torus") { - // Member Data: - // * Rmax - outside radius of the torus tube - // * Rmin - inside radius of the torus tube (Rmin=0 if not hollow) - // * Rtor - radius of the torus itself - // * - // * SPhi - starting angle of the segment in radians - // * DPhi - delta angle of the segment in radians - // - // shape parameters - double Rmin = 0.; - double Rmax = 0.; - double Rtor = 0.; - double SPhi = 0.; - double DPhi = 0.; - // get parameters from DB string - for( auto& par : shapePars) { - std::vector<std::string> vars = splitString(par, '='); - std::string varName = vars[0]; - std::string varValue = vars[1]; - if (varName == "Rmin") Rmin = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "Rmax") Rmax = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "Rtor") Rtor = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "SPhi") SPhi = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "DPhi") DPhi = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - } - shape = new GeoTorus (Rmin, Rmax, Rtor, SPhi, DPhi); - } - else if (type == "Para") { - // shape parameters - double XHalfLength = 0.; - double YHalfLength = 0.; - double ZHalfLength = 0.; - double Alpha = 0.; - double Theta = 0.; - double Phi = 0.; - // get parameters from DB string - for( auto& par : shapePars) { - std::vector<std::string> vars = splitString(par, '='); - std::string varName = vars[0]; - std::string varValue = vars[1]; - if (varName == "XHalfLength") XHalfLength = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "YHalfLength") YHalfLength = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "ZHalfLength") ZHalfLength = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "Alpha") Alpha = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "Theta") Theta = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "Phi") Phi = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - } - shape = new GeoPara (XHalfLength, YHalfLength, ZHalfLength, Alpha, Theta, Phi); - } - else if (type == "Pcon") { - // shape parameters - double SPhi = 0.; - double DPhi = 0.; - unsigned int NZPlanes = 0; - - bool error = 0; - std::string par; - std::vector<std::string> vars; - std::string varName; - std::string varValue; - - GeoPcon* pcon = nullptr; - - int sizePars = shapePars.size(); - // check if we have more than 3 parameters - if (sizePars > 3) { - - // get the three first GeoPcon parameters: the SPhi and DPhi angles, plus the number of Z planes - for( int it=0; it < 3; it++) { - par = shapePars[it]; - vars = splitString(par, '='); - varName = vars[0]; - varValue = vars[1]; - if (varName == "SPhi") SPhi = std::stod(varValue); - if (varName == "DPhi") DPhi = std::stod(varValue); - if (varName == "NZPlanes") NZPlanes = std::stoi(varValue); - } - // build the basic GeoPcon shape - pcon = new GeoPcon(SPhi, DPhi); - - // and now loop over the rest of the list, to get the parameters of all Z planes - for (int it=3; it < sizePars; it++) - { - par = shapePars[it]; - vars = splitString(par, '='); - varName = vars[0]; - varValue = vars[1]; - - if (varName == "ZPos") { - - double zpos = std::stod(varValue); - double rmin=0., rmax=0.; - - it++; // go to next variable - - par = shapePars[it]; - vars = splitString(par, '='); - varName = vars[0]; - varValue = vars[1]; - if (varName == "ZRmin") rmin = std::stod(varValue); - else error = 1; - it++; // go to next variable - - par = shapePars[it]; - vars = splitString(par, '='); - varName = vars[0]; - varValue = vars[1]; - if (varName == "ZRmax") rmax = std::stod(varValue); - else error = 1; - - if(error) { + // Get shape's parameters from the stored string. + // This will be interpreted differently according to the shape. + std::vector<std::string> shapePars = splitString(parameters, ';'); + + GeoShape* shape = nullptr; + + if (type == "Box") { + // shape parameters + double XHalfLength = 0.; + double YHalfLength = 0.; + double ZHalfLength = 0.; + // get parameters from DB string + for (auto& par : shapePars) { + std::vector<std::string> vars = splitString(par, '='); + std::string varName = vars[0]; + std::string varValue = vars[1]; + if (varName == "XHalfLength") + XHalfLength = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "YHalfLength") + YHalfLength = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "ZHalfLength") + ZHalfLength = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + } + shape = new GeoBox(XHalfLength, YHalfLength, ZHalfLength); + } else if (type == "Cons") { + // shape parameters + double RMin1 = 0.; + double RMin2 = 0.; + double RMax1 = 0.; + double RMax2 = 0.; + double DZ = 0.; + double SPhi = 0.; + double DPhi = 0.; + // get parameters from DB string + for (auto& par : shapePars) { + std::vector<std::string> vars = splitString(par, '='); + std::string varName = vars[0]; + std::string varValue = vars[1]; + // std::cout << "varValue Cons:" << varValue; + if (varName == "RMin1") + RMin1 = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "RMin2") + RMin2 = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "RMax1") + RMax1 = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "RMax2") + RMax2 = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "DZ") + DZ = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "SPhi") + SPhi = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "DPhi") + DPhi = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + } + shape = new GeoCons(RMin1, RMin2, RMax1, RMax2, DZ, SPhi, DPhi); + } else if (type == "Torus") { + // Member Data: + // * Rmax - outside radius of the torus tube + // * Rmin - inside radius of the torus tube (Rmin=0 if not hollow) + // * Rtor - radius of the torus itself + // * + // * SPhi - starting angle of the segment in radians + // * DPhi - delta angle of the segment in radians + // + // shape parameters + double Rmin = 0.; + double Rmax = 0.; + double Rtor = 0.; + double SPhi = 0.; + double DPhi = 0.; + // get parameters from DB string + for (auto& par : shapePars) { + std::vector<std::string> vars = splitString(par, '='); + std::string varName = vars[0]; + std::string varValue = vars[1]; + if (varName == "Rmin") + Rmin = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "Rmax") + Rmax = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "Rtor") + Rtor = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "SPhi") + SPhi = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "DPhi") + DPhi = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + } + shape = new GeoTorus(Rmin, Rmax, Rtor, SPhi, DPhi); + } else if (type == "Para") { + // shape parameters + double XHalfLength = 0.; + double YHalfLength = 0.; + double ZHalfLength = 0.; + double Alpha = 0.; + double Theta = 0.; + double Phi = 0.; + // get parameters from DB string + for (auto& par : shapePars) { + std::vector<std::string> vars = splitString(par, '='); + std::string varName = vars[0]; + std::string varValue = vars[1]; + if (varName == "XHalfLength") + XHalfLength = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "YHalfLength") + YHalfLength = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "ZHalfLength") + ZHalfLength = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "Alpha") + Alpha = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "Theta") + Theta = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "Phi") + Phi = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + } + shape = new GeoPara(XHalfLength, YHalfLength, ZHalfLength, Alpha, Theta, + Phi); + } else if (type == "Pcon") { + // shape parameters + double SPhi = 0.; + double DPhi = 0.; + unsigned int NZPlanes = 0; + + bool error = 0; + std::string par; + std::vector<std::string> vars; + std::string varName; + std::string varValue; + + GeoPcon* pcon = nullptr; + + int sizePars = shapePars.size(); + // check if we have more than 3 parameters + if (sizePars > 3) { + // get the three first GeoPcon parameters: the SPhi and DPhi angles, + // plus the number of Z planes + for (int it = 0; it < 3; it++) { + par = shapePars[it]; + vars = splitString(par, '='); + varName = vars[0]; + varValue = vars[1]; + if (varName == "SPhi") SPhi = std::stod(varValue); + if (varName == "DPhi") DPhi = std::stod(varValue); + if (varName == "NZPlanes") NZPlanes = std::stoi(varValue); + } + // build the basic GeoPcon shape + pcon = new GeoPcon(SPhi, DPhi); + + // and now loop over the rest of the list, to get the parameters of + // all Z planes + for (int it = 3; it < sizePars; it++) { + par = shapePars[it]; + vars = splitString(par, '='); + varName = vars[0]; + varValue = vars[1]; + + if (varName == "ZPos") { + double zpos = std::stod(varValue); + double rmin = 0., rmax = 0.; + + it++; // go to next variable + + par = shapePars[it]; + vars = splitString(par, '='); + varName = vars[0]; + varValue = vars[1]; + if (varName == "ZRmin") + rmin = std::stod(varValue); + else + error = 1; + it++; // go to next variable + + par = shapePars[it]; + vars = splitString(par, '='); + varName = vars[0]; + varValue = vars[1]; + if (varName == "ZRmax") + rmax = std::stod(varValue); + else + error = 1; + + if (error) { + muxCout.lock(); + std::cout << "ERROR! GeoPcon 'ZRmin' and 'ZRmax' " + "values are not at the right place! --> "; + printStdVectorStrings(shapePars); + muxCout.unlock(); + } + + // add a Z plane to the GeoPcon + pcon->addPlane(zpos, rmin, rmax); + } else { + error = 1; + muxCout.lock(); + std::cout << "ERROR! GeoPcon 'ZPos' value is not at the " + "right place! --> "; + printStdVectorStrings(shapePars); + muxCout.unlock(); + } + } + + // sanity check on the resulting Pcon shape + if (pcon->getNPlanes() != NZPlanes) { + error = 1; + muxCout.lock(); + std::cout << "ERROR! GeoPcon number of planes: " + << pcon->getNPlanes() + << " is not equal to the original size! --> "; + printStdVectorStrings(shapePars); + muxCout.unlock(); + } + if (!pcon->isValid()) { + error = 1; + muxCout.lock(); + std::cout << "ERROR! GeoPcon shape is not valid!! -- input: "; + printStdVectorStrings(shapePars); + muxCout.unlock(); + } + } // end if (size>3) + else { muxCout.lock(); - std::cout << "ERROR! GeoPcon 'ZRmin' and 'ZRmax' values are not at the right place! --> "; + std::cout << "ERROR!! GeoPcon has no Z planes!! --> shape input " + "parameters: "; printStdVectorStrings(shapePars); muxCout.unlock(); - } + error = 1; + } - // add a Z plane to the GeoPcon - pcon->addPlane(zpos, rmin, rmax); - } else { - error = 1; - muxCout.lock(); - std::cout << "ERROR! GeoPcon 'ZPos' value is not at the right place! --> "; - printStdVectorStrings(shapePars); - muxCout.unlock(); - } - } + if (error) { + muxCout.lock(); + std::cout << "FATAL ERROR!!! - GeoPcon shape error!!! Aborting..." + << std::endl; + muxCout.unlock(); + exit(EXIT_FAILURE); + } - // sanity check on the resulting Pcon shape - if( pcon->getNPlanes() != NZPlanes) { - error = 1; - muxCout.lock(); - std::cout << "ERROR! GeoPcon number of planes: " << pcon->getNPlanes() << " is not equal to the original size! --> "; - printStdVectorStrings(shapePars); - muxCout.unlock(); - } - if(!pcon->isValid()) { - error = 1; - muxCout.lock(); - std::cout << "ERROR! GeoPcon shape is not valid!! -- input: "; - printStdVectorStrings(shapePars); - muxCout.unlock(); - } - } // end if (size>3) - else { - muxCout.lock(); - std::cout << "ERROR!! GeoPcon has no Z planes!! --> shape input parameters: "; - printStdVectorStrings(shapePars); - muxCout.unlock(); - error = 1; - } - - if(error) { - muxCout.lock(); - std::cout << "FATAL ERROR!!! - GeoPcon shape error!!! Aborting..." << std::endl; - muxCout.unlock(); - exit(EXIT_FAILURE); - } - - shape = pcon; - } - else if (type == "Pgon") { - // shape parameters - double SPhi = 0.; - double DPhi = 0.; - unsigned int NSides = 0; - unsigned int NZPlanes = 0; - - bool error = false; - GeoPgon* pgon = nullptr; - - std::string par; - std::vector<std::string> vars; - std::string varName; - std::string varValue; - - int sizePars = shapePars.size(); - // check if we have more than 3 parameters - if (sizePars > 3) { - - // get the first four GeoPgon parameters: the SPhi and DPhi angles, plus the number of Z planes - for( int it=0; it < 4; it++) { - par = shapePars[it]; - vars = splitString(par, '='); - varName = vars[0]; - varValue = vars[1]; - // qInfo() << "vars: " << vars; // for debug only - if (varName == "SPhi") SPhi = std::stod(varValue); - if (varName == "DPhi") DPhi = std::stod(varValue); - if (varName == "NSides") NSides = std::stoi(varValue); - if (varName == "NZPlanes") NZPlanes = std::stoi(varValue); - - } - // build the basic GeoPgon shape - pgon = new GeoPgon(SPhi, DPhi, NSides); - - // and now loop over the rest of the list, to get the parameters of all Z planes - for (int it=4; it < sizePars; it++) - { - par = shapePars[it]; - vars = splitString(par, '='); - varName = vars[0]; - varValue = vars[1]; - - if (varName == "ZPos") { - - double zpos = std::stod(varValue); - double rmin=0., rmax=0.; - - it++; // go to next variable - - par = shapePars[it]; - vars = splitString(par, '='); - varName = vars[0]; - varValue = vars[1]; - if (varName == "ZRmin") rmin = std::stod(varValue); - else error = 1; - it++; // go to next variable - - par = shapePars[it]; - vars = splitString(par, '='); - varName = vars[0]; - varValue = vars[1]; - if (varName == "ZRmax") rmax = std::stod(varValue); - else error = 1; - - if(error) { + shape = pcon; + } else if (type == "Pgon") { + // shape parameters + double SPhi = 0.; + double DPhi = 0.; + unsigned int NSides = 0; + unsigned int NZPlanes = 0; + + bool error = false; + GeoPgon* pgon = nullptr; + + std::string par; + std::vector<std::string> vars; + std::string varName; + std::string varValue; + + int sizePars = shapePars.size(); + // check if we have more than 3 parameters + if (sizePars > 3) { + // get the first four GeoPgon parameters: the SPhi and DPhi angles, + // plus the number of Z planes + for (int it = 0; it < 4; it++) { + par = shapePars[it]; + vars = splitString(par, '='); + varName = vars[0]; + varValue = vars[1]; + // qInfo() << "vars: " << vars; // for debug only + if (varName == "SPhi") SPhi = std::stod(varValue); + if (varName == "DPhi") DPhi = std::stod(varValue); + if (varName == "NSides") NSides = std::stoi(varValue); + if (varName == "NZPlanes") NZPlanes = std::stoi(varValue); + } + // build the basic GeoPgon shape + pgon = new GeoPgon(SPhi, DPhi, NSides); + + // and now loop over the rest of the list, to get the parameters of + // all Z planes + for (int it = 4; it < sizePars; it++) { + par = shapePars[it]; + vars = splitString(par, '='); + varName = vars[0]; + varValue = vars[1]; + + if (varName == "ZPos") { + double zpos = std::stod(varValue); + double rmin = 0., rmax = 0.; + + it++; // go to next variable + + par = shapePars[it]; + vars = splitString(par, '='); + varName = vars[0]; + varValue = vars[1]; + if (varName == "ZRmin") + rmin = std::stod(varValue); + else + error = 1; + it++; // go to next variable + + par = shapePars[it]; + vars = splitString(par, '='); + varName = vars[0]; + varValue = vars[1]; + if (varName == "ZRmax") + rmax = std::stod(varValue); + else + error = 1; + + if (error) { + muxCout.lock(); + std::cout << "ERROR! GeoPgon 'ZRmin' and 'ZRmax' " + "values are not at the right place! --> "; + printStdVectorStrings(shapePars); + muxCout.unlock(); + } + + // add a Z plane to the GeoPgon + pgon->addPlane(zpos, rmin, rmax); + } else { + error = 1; + muxCout.lock(); + std::cout << "ERROR! GeoPgon 'ZPos' value is not at the " + "right place! --> "; + printStdVectorStrings(shapePars); + muxCout.unlock(); + } + } + + // sanity check on the resulting Pgon shape + if (pgon->getNPlanes() != NZPlanes) { + error = 1; + muxCout.lock(); + std::cout << "ERROR! GeoPgon number of planes: " + << pgon->getNPlanes() + << " is not equal to the original size! --> "; + printStdVectorStrings(shapePars); + muxCout.unlock(); + } + if (!pgon->isValid()) { + error = 1; + muxCout.lock(); + std::cout << "ERROR! GeoPgon shape is not valid!! -- input: "; + printStdVectorStrings(shapePars); + muxCout.unlock(); + } + } // end if (size>3) + else { muxCout.lock(); - std::cout << "ERROR! GeoPgon 'ZRmin' and 'ZRmax' values are not at the right place! --> "; + std::cout << "ERROR!! GeoPgon has no Z planes!! --> shape input " + "parameters: "; printStdVectorStrings(shapePars); muxCout.unlock(); - } - - // add a Z plane to the GeoPgon - pgon->addPlane(zpos, rmin, rmax); - } else { - error = 1; - muxCout.lock(); - std::cout << "ERROR! GeoPgon 'ZPos' value is not at the right place! --> "; - printStdVectorStrings(shapePars); - muxCout.unlock(); - } - } + error = 1; + } + if (error) { + muxCout.lock(); + std::cout << "FATAL ERROR!!! - GeoPgon shape error!!! Aborting..." + << std::endl; + muxCout.unlock(); + exit(EXIT_FAILURE); + } + shape = pgon; + } else if (type == "GenericTrap") { + // shape parameters + double ZHalfLength = 0.; + unsigned int NVertices = 0; + GeoGenericTrapVertices Vertices; + bool error = false; + GeoGenericTrap* gTrap = nullptr; + + std::string par; + std::vector<std::string> vars; + std::string varName; + std::string varValue; + + int sizePars = shapePars.size(); + // check if we have more than 3 parameters + if (sizePars > 3) { + // get the two GeoGenericTrap parameters: the ZHalfLength plus the + // number of vertices + for (int it = 0; it < 2; it++) { + par = shapePars[it]; + vars = splitString(par, '='); + varName = vars[0]; + varValue = vars[1]; + // qInfo() << "vars: " << vars; // for debug only + if (varName == "ZHalfLength") ZHalfLength = std::stod(varValue); + if (varName == "NVertices") NVertices = std::stoi(varValue); + } - // sanity check on the resulting Pgon shape - if( pgon->getNPlanes() != NZPlanes) { - error = 1; - muxCout.lock(); - std::cout << "ERROR! GeoPgon number of planes: " << pgon->getNPlanes() << " is not equal to the original size! --> "; - printStdVectorStrings(shapePars); - muxCout.unlock(); - } - if(!pgon->isValid()) { - error = 1; - muxCout.lock(); - std::cout << "ERROR! GeoPgon shape is not valid!! -- input: "; - printStdVectorStrings(shapePars); - muxCout.unlock(); - } - } // end if (size>3) - else { - muxCout.lock(); - std::cout << "ERROR!! GeoPgon has no Z planes!! --> shape input parameters: "; - printStdVectorStrings(shapePars); - muxCout.unlock(); - error = 1; - } - if(error) { - muxCout.lock(); - std::cout << "FATAL ERROR!!! - GeoPgon shape error!!! Aborting..." << std::endl; - muxCout.unlock(); - exit(EXIT_FAILURE); - } - shape = pgon; - } - else if (type == "GenericTrap") { - // shape parameters - double ZHalfLength = 0.; - unsigned int NVertices = 0; - GeoGenericTrapVertices Vertices; - bool error = false; - GeoGenericTrap* gTrap = nullptr; - - std::string par; - std::vector<std::string> vars; - std::string varName; - std::string varValue; - - int sizePars = shapePars.size(); - // check if we have more than 3 parameters - if (sizePars > 3) { - - // get the two GeoGenericTrap parameters: the ZHalfLength plus the number of vertices - for( int it=0; it < 2; it++) { - par = shapePars[it]; - vars = splitString(par, '='); - varName = vars[0]; - varValue = vars[1]; - // qInfo() << "vars: " << vars; // for debug only - if (varName == "ZHalfLength") ZHalfLength = std::stod(varValue); - if (varName == "NVertices") NVertices = std::stoi(varValue); - } - - - - // and now loop over the rest of the list, to get the parameters of all Z planes - for (unsigned it=2; it < NVertices*2+1; it++) - { - par = shapePars[it]; - vars = splitString(par, '='); - varName = vars[0]; - varValue = vars[1]; - - if (varName == "X") { - - double x = std::stod(varValue); - - it++; // go to next variable - - par = shapePars[it]; - vars = splitString(par, '='); - varName = vars[0]; - varValue = vars[1]; - if (varName == "Y") { - double y = std::stod(varValue); - Vertices.push_back(GeoTwoVector(x,y)); - } - else { - error = 1; - } - if(error) { + // and now loop over the rest of the list, to get the parameters of + // all Z planes + for (unsigned it = 2; it < NVertices * 2 + 1; it++) { + par = shapePars[it]; + vars = splitString(par, '='); + varName = vars[0]; + varValue = vars[1]; + + if (varName == "X") { + double x = std::stod(varValue); + + it++; // go to next variable + + par = shapePars[it]; + vars = splitString(par, '='); + varName = vars[0]; + varValue = vars[1]; + if (varName == "Y") { + double y = std::stod(varValue); + Vertices.push_back(GeoTwoVector(x, y)); + } else { + error = 1; + } + if (error) { + muxCout.lock(); + std::cout << "ERROR! GeoGenericTrap 'X' and 'Y' values " + "are not at the right place! --> "; + printStdVectorStrings(shapePars); + muxCout.unlock(); + } + } else { + error = 1; + muxCout.lock(); + std::cout << "ERROR! GeoGenericTrap 'ZPos' value is not at " + "the right place! --> "; + printStdVectorStrings(shapePars); + muxCout.unlock(); + } + } + if (error) { + muxCout.lock(); + std::cout << "FATAL ERROR!!! - GeoGenericTrap shape error!!! " + "Aborting..." + << std::endl; + muxCout.unlock(); + exit(EXIT_FAILURE); + } + // build the basic GenericTrap shape + gTrap = new GeoGenericTrap(ZHalfLength, Vertices); + } // end if (size>3) + else { muxCout.lock(); - std::cout << "ERROR! GeoGenericTrap 'X' and 'Y' values are not at the right place! --> "; + std::cout << "ERROR!! GeoGenericTrap has no Z vertices!! --> shape " + "input parameters: "; printStdVectorStrings(shapePars); muxCout.unlock(); - } - } else { - error = 1; - muxCout.lock(); - std::cout << "ERROR! GeoGenericTrap 'ZPos' value is not at the right place! --> "; - printStdVectorStrings(shapePars); - muxCout.unlock(); - } - } - if(error) { - muxCout.lock(); - std::cout << "FATAL ERROR!!! - GeoGenericTrap shape error!!! Aborting..." << std::endl; - muxCout.unlock(); - exit(EXIT_FAILURE); - } - // build the basic GenericTrap shape - gTrap = new GeoGenericTrap(ZHalfLength,Vertices); - } // end if (size>3) - else { - muxCout.lock(); - std::cout << "ERROR!! GeoGenericTrap has no Z vertices!! --> shape input parameters: "; - printStdVectorStrings(shapePars); - muxCout.unlock(); - error = 1; - } - if(error) { - muxCout.lock(); - std::cout << "FATAL ERROR!!! - GeoGenericTrap shape error!!! Aborting..." << std::endl; - muxCout.unlock(); - exit(EXIT_FAILURE); - } - shape = gTrap; - } - else if (type == "SimplePolygonBrep") { - // shape parameters - double DZ = 0.; - unsigned int NVertices = 0; - double xV = 0.; - double yV = 0.; - - bool error = 0; - GeoSimplePolygonBrep* sh = nullptr; - - std::string par; - std::vector<std::string> vars; - std::string varName; - std::string varValue; - - int sizePars = shapePars.size(); - // check if we have more than 2 parameters - if (sizePars > 2) { - - // get the first two GeoSimplePolygonBrep parameters: DZ and the number of vertices. - for( int it=0; it < 2; it++) { - par = shapePars[it]; - vars = splitString(par, '='); - varName = vars[0]; - varValue = vars[1]; - if (varName == "DZ") DZ = std::stod(varValue); - if (varName == "NVertices") NVertices = std::stoi(varValue); - //else if (varName == "NVertices") NVertices = varValue.toDouble(); - //else error = 1; - //if(error) std::cout << "ERROR! GeoSimplePolygonBrep parameters are not correctly stored! -->" << vars; - - } - // build the basic GeoSimplePolygonBrep shape - sh = new GeoSimplePolygonBrep(DZ); - - // and now loop over the rest of the list, to get the parameters of all vertices - for (int it=2; it < sizePars; it++) - { - par = shapePars[it]; - vars = splitString(par, '='); - varName = vars[0]; - varValue = vars[1]; - if (varName == "xV") xV = std::stod(varValue); - else error = 1; - - it++; // go to next variable (they come in pairs) - - par = shapePars[it]; - vars = splitString(par, '='); - varName = vars[0]; - varValue = vars[1]; - if (varName == "yV") yV = std::stod(varValue); - else error = 1; - - if(error) { - muxCout.lock(); - std::cout << "ERROR! GeoSimplePolygonBrep 'xVertex' and 'yVertex' values are not at the right place! --> "; - printStdVectorStrings(shapePars); - muxCout.unlock(); + error = 1; } + if (error) { + muxCout.lock(); + std::cout + << "FATAL ERROR!!! - GeoGenericTrap shape error!!! Aborting..." + << std::endl; + muxCout.unlock(); + exit(EXIT_FAILURE); + } + shape = gTrap; + } else if (type == "SimplePolygonBrep") { + // shape parameters + double DZ = 0.; + unsigned int NVertices = 0; + double xV = 0.; + double yV = 0.; + + bool error = 0; + GeoSimplePolygonBrep* sh = nullptr; + + std::string par; + std::vector<std::string> vars; + std::string varName; + std::string varValue; + + int sizePars = shapePars.size(); + // check if we have more than 2 parameters + if (sizePars > 2) { + // get the first two GeoSimplePolygonBrep parameters: DZ and the + // number of vertices. + for (int it = 0; it < 2; it++) { + par = shapePars[it]; + vars = splitString(par, '='); + varName = vars[0]; + varValue = vars[1]; + if (varName == "DZ") DZ = std::stod(varValue); + if (varName == "NVertices") NVertices = std::stoi(varValue); + // else if (varName == "NVertices") NVertices = + // varValue.toDouble(); else error = 1; if(error) std::cout << + // "ERROR! GeoSimplePolygonBrep parameters are not correctly + // stored! -->" << vars; + } + // build the basic GeoSimplePolygonBrep shape + sh = new GeoSimplePolygonBrep(DZ); + + // and now loop over the rest of the list, to get the parameters of + // all vertices + for (int it = 2; it < sizePars; it++) { + par = shapePars[it]; + vars = splitString(par, '='); + varName = vars[0]; + varValue = vars[1]; + if (varName == "xV") + xV = std::stod(varValue); + else + error = 1; + + it++; // go to next variable (they come in pairs) + + par = shapePars[it]; + vars = splitString(par, '='); + varName = vars[0]; + varValue = vars[1]; + if (varName == "yV") + yV = std::stod(varValue); + else + error = 1; + + if (error) { + muxCout.lock(); + std::cout << "ERROR! GeoSimplePolygonBrep 'xVertex' and " + "'yVertex' values are not at the right place! " + "--> "; + printStdVectorStrings(shapePars); + muxCout.unlock(); + } - // add a Z plane to the GeoSimplePolygonBrep - sh->addVertex(xV, yV); - } - // sanity check on the resulting shape - if( sh->getNVertices() != NVertices) { - error = 1; - muxCout.lock(); - std::cout << "ERROR! GeoSimplePolygonBrep number of planes: " << sh->getNVertices() << " is not equal to the original size! --> "; - printStdVectorStrings(shapePars); - muxCout.unlock(); - } - if(!sh->isValid()) { - error = 1; - muxCout.lock(); - std::cout << "ERROR! GeoSimplePolygonBrep shape is not valid!! -- input: "; - printStdVectorStrings(shapePars); - muxCout.unlock(); - } - } // end if (size>3) - else { - muxCout.lock(); - std::cout << "ERROR!! GeoSimplePolygonBrep has no vertices!! --> shape input parameters: "; - printStdVectorStrings(shapePars); - muxCout.unlock(); - error = 1; - } - if(error) { - muxCout.lock(); - std::cout << "FATAL ERROR!!! - GeoSimplePolygonBrep shape error!!! Aborting..." << std::endl; - muxCout.unlock(); - exit(EXIT_FAILURE); - } - shape = sh; - - } - else if (type == "TessellatedSolid") { - // Tessellated pars example: "nFacets=1;TRI;vT=ABSOLUTE;nV=3;xV=0;yV=0;zV=1;xV=0;yV=1;zV=0;xV=1;yV=0;zV=0" - std::cout << "Reading-in: TessellatedSolid: "; // debug - // Facet type - std::string facetType = ""; - // shape parameters - unsigned int nFacets = 0; - - bool error = 0; - GeoTessellatedSolid* sh = nullptr; - - std::string par; - std::vector<std::string> vars; - std::string varName; - std::string varValue; - - int sizePars = shapePars.size(); - // check if we have at least 13 parameters, - // which is the minimum for a shape - // with a single triangular facet - if (sizePars >= 13) { - - // get the first parameter - par = shapePars[0]; - vars = splitString(par, '='); - varName = vars[0]; - varValue = vars[1]; - if (varName == "nFacets") nFacets = std::stoi(varValue); - else { - muxCout.lock(); -// qWarning("ERROR!! - GeoTessellatedSolid - nFacets is not defined!!"); - muxCout.unlock(); - error = true; // TODO: check "error.h" functionalities and replace with that, if useful - } - - // build the basic GeoTessellatedSolid shape - sh = new GeoTessellatedSolid(); - - // and now loop over the rest of the list, - // to get the parameters of the vertices of each facet - // and to build the full GeoTessellatedSolid with all the facets - for (int it=1; it < sizePars; it++) - { - // get facet type - par = shapePars[it]; - vars = splitString(par, '='); - varName = vars[0]; - if (varName == "QUAD") { - facetType = "QUAD"; - } - else if (varName == "TRI") { - facetType = "TRI"; - } - else { - muxCout.lock(); - std::cout << "ERROR!! - GeoTessellatedSolid - Facet type is not defined! [got: '" << varName << "']" << std::endl; - muxCout.unlock(); - error = true; - } - - it++; // advance to the next parameter - - // get the type of the vertexes composing the facet - bool isAbsolute = true; - par = shapePars[it]; - vars = splitString(par, '='); - varName = vars[0]; - varValue = vars[1]; - if (varName == "vT") { - if (varValue == "ABSOLUTE") isAbsolute = true; - else if (varValue == "RELATIVE") isAbsolute = false; - else { + // add a Z plane to the GeoSimplePolygonBrep + sh->addVertex(xV, yV); + } + // sanity check on the resulting shape + if (sh->getNVertices() != NVertices) { + error = 1; + muxCout.lock(); + std::cout << "ERROR! GeoSimplePolygonBrep number of planes: " + << sh->getNVertices() + << " is not equal to the original size! --> "; + printStdVectorStrings(shapePars); + muxCout.unlock(); + } + if (!sh->isValid()) { + error = 1; + muxCout.lock(); + std::cout << "ERROR! GeoSimplePolygonBrep shape is not valid!! " + "-- input: "; + printStdVectorStrings(shapePars); + muxCout.unlock(); + } + } // end if (size>3) + else { + muxCout.lock(); + std::cout << "ERROR!! GeoSimplePolygonBrep has no vertices!! --> " + "shape input parameters: "; + printStdVectorStrings(shapePars); + muxCout.unlock(); + error = 1; + } + if (error) { muxCout.lock(); - std::cout << "ERROR! - GeoTessellatedSolid - Vertex type not defined!" << std::endl; + std::cout << "FATAL ERROR!!! - GeoSimplePolygonBrep shape error!!! " + "Aborting..." + << std::endl; muxCout.unlock(); - error=true; - } - } - else error = 1; + exit(EXIT_FAILURE); + } + shape = sh; + + } else if (type == "TessellatedSolid") { + // Tessellated pars example: + // "nFacets=1;TRI;vT=ABSOLUTE;nV=3;xV=0;yV=0;zV=1;xV=0;yV=1;zV=0;xV=1;yV=0;zV=0" + std::cout << "Reading-in: TessellatedSolid: "; // debug + // Facet type + std::string facetType = ""; + // shape parameters + unsigned int nFacets = 0; + + bool error = 0; + GeoTessellatedSolid* sh = nullptr; + + std::string par; + std::vector<std::string> vars; + std::string varName; + std::string varValue; + + int sizePars = shapePars.size(); + // check if we have at least 13 parameters, + // which is the minimum for a shape + // with a single triangular facet + if (sizePars >= 13) { + // get the first parameter + par = shapePars[0]; + vars = splitString(par, '='); + varName = vars[0]; + varValue = vars[1]; + if (varName == "nFacets") + nFacets = std::stoi(varValue); + else { + muxCout.lock(); + // qWarning("ERROR!! - GeoTessellatedSolid - nFacets is + // not defined!!"); + muxCout.unlock(); + error = true; // TODO: check "error.h" functionalities and + // replace with that, if useful + } + + // build the basic GeoTessellatedSolid shape + sh = new GeoTessellatedSolid(); + + // and now loop over the rest of the list, + // to get the parameters of the vertices of each facet + // and to build the full GeoTessellatedSolid with all the facets + for (int it = 1; it < sizePars; it++) { + // get facet type + par = shapePars[it]; + vars = splitString(par, '='); + varName = vars[0]; + if (varName == "QUAD") { + facetType = "QUAD"; + } else if (varName == "TRI") { + facetType = "TRI"; + } else { + muxCout.lock(); + std::cout << "ERROR!! - GeoTessellatedSolid - Facet type " + "is not defined! [got: '" + << varName << "']" << std::endl; + muxCout.unlock(); + error = true; + } - it++; // advance to the next parameter + it++; // advance to the next parameter + + // get the type of the vertexes composing the facet + bool isAbsolute = true; + par = shapePars[it]; + vars = splitString(par, '='); + varName = vars[0]; + varValue = vars[1]; + if (varName == "vT") { + if (varValue == "ABSOLUTE") + isAbsolute = true; + else if (varValue == "RELATIVE") + isAbsolute = false; + else { + muxCout.lock(); + std::cout << "ERROR! - GeoTessellatedSolid - Vertex " + "type not defined!" + << std::endl; + muxCout.unlock(); + error = true; + } + } else + error = 1; + + it++; // advance to the next parameter /* - unsigned int nVertexes = 0; // TODO: check how this is used - par = shapePars[it]; - vars = splitString(par, '='); - varName = vars[0]; - varValue = vars[1]; - if (varName == "nV") { + unsigned int nVertexes = 0; // TODO: check how + this is used par = shapePars[it]; vars = splitString(par, '='); + varName = vars[0]; + varValue = vars[1]; + if (varName == "nV") { nVertexes = std::stoi(varValue); } - else { + else { muxCout.lock(); - std::cout << "ERROR! - GeoTessellatedSolid - nVertices not defined!" << std::endl; + std::cout << "ERROR! - + GeoTessellatedSolid - nVertices not defined!" << std::endl; muxCout.unlock(); - error=true; - } + error=true; + } */ - // if we get a QUAD ==> GeoQuadrangularFacet - if (facetType=="QUAD") { - - muxCout.lock(); - std::cout << "Handling a QUAD facet..." << std::endl; - muxCout.unlock(); - // to store the 4 vertices of the GeoQuadrangularFacet - auto vV = std::vector<std::unique_ptr<GeoFacetVertex>>{}; - - // we look for 4 vertices for QUAD; - // for each of them, we get 3 coordinates - // vertStart = it; - for (unsigned int iV=0; iV<4; ++iV) { - - it++; // advance to the first of the facet's vertices' coordinates - - double xV=0.; - par = shapePars[it]; - vars = splitString(par, '='); - varName = vars[0]; - varValue = vars[1]; - if (varName == "xV") xV = std::stod(varValue); - else { - muxCout.lock(); - std::cout << "ERROR! Got '" << varName << "' instead of 'xV'!" << std::endl; - muxCout.unlock(); - error = 1; - } - - it++; // go to the next coordinate - - double yV=0.; - par = shapePars[it]; - vars = splitString(par, '='); - varName = vars[0]; - varValue = vars[1]; - if (varName == "yV") yV = std::stod(varValue); - else { - muxCout.lock(); - std::cout << "ERROR! Got '" << varName << "' instead of 'yV'!" << std::endl; - muxCout.unlock(); - error = 1; - } - - it++; // go to the next coordinate - - double zV=0.; - par = shapePars[it]; - vars = splitString(par, '='); - varName = vars[0]; - varValue = vars[1]; - if (varName == "zV") zV = std::stod(varValue); - else { - muxCout.lock(); - std::cout << "ERROR! Got '" << varName << "' instead of 'zV'!" << std::endl; - muxCout.unlock(); - error = 1; - } - - if(error) { - muxCout.lock(); - std::cout << "ERROR! GeoTessellatedSolid 'xV', 'yV', and 'zV' values are not at the right place! --> "; - printStdVectorStrings(shapePars); - muxCout.unlock(); + // if we get a QUAD ==> GeoQuadrangularFacet + if (facetType == "QUAD") { + muxCout.lock(); + std::cout << "Handling a QUAD facet..." << std::endl; + muxCout.unlock(); + // to store the 4 vertices of the GeoQuadrangularFacet + auto vV = std::vector<std::unique_ptr<GeoFacetVertex>>{}; + + // we look for 4 vertices for QUAD; + // for each of them, we get 3 coordinates + // vertStart = it; + for (unsigned int iV = 0; iV < 4; ++iV) { + it++; // advance to the first of the facet's vertices' + // coordinates + + double xV = 0.; + par = shapePars[it]; + vars = splitString(par, '='); + varName = vars[0]; + varValue = vars[1]; + if (varName == "xV") + xV = std::stod(varValue); + else { + muxCout.lock(); + std::cout << "ERROR! Got '" << varName + << "' instead of 'xV'!" << std::endl; + muxCout.unlock(); + error = 1; + } + + it++; // go to the next coordinate + + double yV = 0.; + par = shapePars[it]; + vars = splitString(par, '='); + varName = vars[0]; + varValue = vars[1]; + if (varName == "yV") + yV = std::stod(varValue); + else { + muxCout.lock(); + std::cout << "ERROR! Got '" << varName + << "' instead of 'yV'!" << std::endl; + muxCout.unlock(); + error = 1; + } + + it++; // go to the next coordinate + + double zV = 0.; + par = shapePars[it]; + vars = splitString(par, '='); + varName = vars[0]; + varValue = vars[1]; + if (varName == "zV") + zV = std::stod(varValue); + else { + muxCout.lock(); + std::cout << "ERROR! Got '" << varName + << "' instead of 'zV'!" << std::endl; + muxCout.unlock(); + error = 1; + } + + if (error) { + muxCout.lock(); + std::cout << "ERROR! GeoTessellatedSolid 'xV', " + "'yV', and 'zV' values are not at the " + "right place! --> "; + printStdVectorStrings(shapePars); + muxCout.unlock(); + } + + // build the facet's vertex and store it + vV.push_back(std::make_unique<GeoFacetVertex>( + GeoFacetVertex(xV, yV, zV))); + } + + // build the facet and add it to the GeoTessellatedSolid + GeoQuadrangularFacet* quadFacet = new GeoQuadrangularFacet( + *vV[0], *vV[1], *vV[2], *vV[3], + (isAbsolute ? GeoFacet::ABSOLUTE : GeoFacet::RELATIVE)); + sh->addFacet(quadFacet); + } + // if we get a TRI ==> GeoTriangularFacet + else if (facetType == "TRI") { + muxCout.lock(); + std::cout << "Handling a TRI facet..." << std::endl; + muxCout.unlock(); + + // std::vector<GeoFacetVertex*> vV(3, 0); // to store the 3 + // vertices of the GeoTriangularFacet + auto vV = std::vector<std::unique_ptr<GeoFacetVertex>>{}; + + // we look for 3 vertices for GeoTriangularFacet; + // for each of them, we get 3 coordinates + // vertStart = it; + for (unsigned int iV = 0; iV < 3; ++iV) { + it++; // advance to the first of the facet's vertices' + // coordinates + + double xV = 0.; + par = shapePars[it]; + vars = splitString(par, '='); + varName = vars[0]; + varValue = vars[1]; + if (varName == "xV") + xV = std::stod(varValue); + else + error = 1; + + it++; // go to the next coordinate + + double yV = 0.; + par = shapePars[it]; + vars = splitString(par, '='); + varName = vars[0]; + varValue = vars[1]; + if (varName == "yV") + yV = std::stod(varValue); + else + error = 1; + + it++; // go to the next coordinate + + double zV = 0.; + par = shapePars[it]; + vars = splitString(par, '='); + varName = vars[0]; + varValue = vars[1]; + if (varName == "zV") + zV = std::stod(varValue); + else + error = 1; + + if (error) { + muxCout.lock(); + std::cout << "ERROR! GeoTessellatedSolid 'xV', " + "'yV', and 'zV' values are not at the " + "right place! --> "; + printStdVectorStrings(shapePars); + muxCout.unlock(); + } + + // build the facet's vertex and store it + vV.push_back(std::make_unique<GeoFacetVertex>( + GeoFacetVertex(xV, yV, zV))); + } + + // build the facet and add it to the GeoTessellatedSolid + GeoTriangularFacet* triFacet = new GeoTriangularFacet( + *vV[0], *vV[1], *vV[2], + (isAbsolute ? GeoFacet::ABSOLUTE : GeoFacet::RELATIVE)); + sh->addFacet(triFacet); + } } - // build the facet's vertex and store it - vV.push_back(std::make_unique<GeoFacetVertex>( GeoFacetVertex(xV,yV,zV)) ); - } - - // build the facet and add it to the GeoTessellatedSolid - GeoQuadrangularFacet* quadFacet = new GeoQuadrangularFacet(*vV[0], *vV[1], *vV[2], *vV[3], (isAbsolute ? GeoFacet::ABSOLUTE : GeoFacet::RELATIVE)); - sh->addFacet(quadFacet); - } - // if we get a TRI ==> GeoTriangularFacet - else if (facetType=="TRI") { - - muxCout.lock(); - std::cout << "Handling a TRI facet..." << std::endl; - muxCout.unlock(); - - // std::vector<GeoFacetVertex*> vV(3, 0); // to store the 3 vertices of the GeoTriangularFacet - auto vV = std::vector<std::unique_ptr<GeoFacetVertex>>{}; - - // we look for 3 vertices for GeoTriangularFacet; - // for each of them, we get 3 coordinates - // vertStart = it; - for (unsigned int iV=0; iV<3; ++iV) { - - it++; // advance to the first of the facet's vertices' coordinates - - double xV=0.; - par = shapePars[it]; - vars = splitString(par, '='); - varName = vars[0]; - varValue = vars[1]; - if (varName == "xV") xV = std::stod(varValue); - else error = 1; - - it++; // go to the next coordinate - - double yV=0.; - par = shapePars[it]; - vars = splitString(par, '='); - varName = vars[0]; - varValue = vars[1]; - if (varName == "yV") yV = std::stod(varValue); - else error = 1; - - it++; // go to the next coordinate - - double zV=0.; - par = shapePars[it]; - vars = splitString(par, '='); - varName = vars[0]; - varValue = vars[1]; - if (varName == "zV") zV = std::stod(varValue); - else error = 1; - - if(error) { - muxCout.lock(); - std::cout << "ERROR! GeoTessellatedSolid 'xV', 'yV', and 'zV' values are not at the right place! --> "; - printStdVectorStrings(shapePars); - muxCout.unlock(); + // sanity check on the resulting shape + if (sh->getNumberOfFacets() != nFacets) { + error = 1; + muxCout.lock(); + std::cout << "ERROR! GeoTessellatedSolid number of facets: " + << sh->getNumberOfFacets() + << " is not equal to the original size! --> "; + printStdVectorStrings(shapePars); + muxCout.unlock(); } + /* + * TODO: uncomment it, when the isValid() method will be implemented + for GeoTessellatedSolid if(!sh->isValid()) { error = 1; std::cout << + "ERROR! GeoTessellatedSolid shape is not valid!! -- input: " << + shapePars; + } + */ + } // END OF if (size>13) + else { + muxCout.lock(); + std::cout << "ERROR!! GeoTessellatedSolid has no facets!! --> " + "shape input parameters: "; + printStdVectorStrings(shapePars); + muxCout.unlock(); + error = 1; + } + if (error) { + muxCout.lock(); + std::cout << "GeoTessellatedSolid shape error!!! Aborting..." + << std::endl; + muxCout.unlock(); + exit(EXIT_FAILURE); + } + shape = sh; - // build the facet's vertex and store it - vV.push_back(std::make_unique<GeoFacetVertex>( GeoFacetVertex(xV,yV,zV)) ); - } - - // build the facet and add it to the GeoTessellatedSolid - GeoTriangularFacet* triFacet = new GeoTriangularFacet(*vV[0], *vV[1], *vV[2], (isAbsolute ? GeoFacet::ABSOLUTE : GeoFacet::RELATIVE)); - sh->addFacet(triFacet); - } - - - } - - // sanity check on the resulting shape - if( sh->getNumberOfFacets() != nFacets) { - error = 1; - muxCout.lock(); - std::cout << "ERROR! GeoTessellatedSolid number of facets: " << sh->getNumberOfFacets() << " is not equal to the original size! --> "; - printStdVectorStrings(shapePars); - muxCout.unlock(); - } - /* - * TODO: uncomment it, when the isValid() method will be implemented for GeoTessellatedSolid - if(!sh->isValid()) { - error = 1; - std::cout << "ERROR! GeoTessellatedSolid shape is not valid!! -- input: " << shapePars; - } - */ - } // END OF if (size>13) - else { - muxCout.lock(); - std::cout << "ERROR!! GeoTessellatedSolid has no facets!! --> shape input parameters: "; - printStdVectorStrings(shapePars); - muxCout.unlock(); - error = 1; - } - if(error) { - muxCout.lock(); - std::cout << "GeoTessellatedSolid shape error!!! Aborting..." << std::endl; - muxCout.unlock(); - exit(EXIT_FAILURE); - } - shape = sh; - - } - else if (type == "Trap") { - // shape constructor parameters - double ZHalfLength = 0.; - double Theta = 0.; - double Phi = 0.; - double Dydzn = 0.; - double Dxdyndzn = 0.; - double Dxdypdzn = 0.; - double Angleydzn = 0.; - double Dydzp = 0.; - double Dxdyndzp = 0.; - double Dxdypdzp = 0.; - double Angleydzp = 0.; - // get parameters - for( auto& par : shapePars) { - std::vector<std::string> vars = splitString(par, '='); - std::string varName = vars[0]; - std::string varValue = vars[1]; - if (varName == "ZHalfLength") ZHalfLength = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "Theta") Theta = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "Phi") Phi = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "Dydzn") Dydzn = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "Dxdyndzn") Dxdyndzn = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "Dxdypdzn") Dxdypdzn = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "Angleydzn") Angleydzn = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "Dydzp") Dydzp = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "Dxdyndzp") Dxdyndzp = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "Dxdypdzp") Dxdypdzp = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "Angleydzp") Angleydzp = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - } - shape = new GeoTrap (ZHalfLength, Theta, Phi, Dydzn, Dxdyndzn, Dxdypdzn, Angleydzn, Dydzp, Dxdyndzp, Dxdypdzp, Angleydzp); - } - else if (type == "TwistedTrap") { + } else if (type == "Trap") { + // shape constructor parameters + double ZHalfLength = 0.; + double Theta = 0.; + double Phi = 0.; + double Dydzn = 0.; + double Dxdyndzn = 0.; + double Dxdypdzn = 0.; + double Angleydzn = 0.; + double Dydzp = 0.; + double Dxdyndzp = 0.; + double Dxdypdzp = 0.; + double Angleydzp = 0.; + // get parameters + for (auto& par : shapePars) { + std::vector<std::string> vars = splitString(par, '='); + std::string varName = vars[0]; + std::string varValue = vars[1]; + if (varName == "ZHalfLength") + ZHalfLength = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "Theta") + Theta = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "Phi") + Phi = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "Dydzn") + Dydzn = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "Dxdyndzn") + Dxdyndzn = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "Dxdypdzn") + Dxdypdzn = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "Angleydzn") + Angleydzn = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "Dydzp") + Dydzp = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "Dxdyndzp") + Dxdyndzp = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "Dxdypdzp") + Dxdypdzp = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "Angleydzp") + Angleydzp = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + } + shape = new GeoTrap(ZHalfLength, Theta, Phi, Dydzn, Dxdyndzn, Dxdypdzn, + Angleydzn, Dydzp, Dxdyndzp, Dxdypdzp, Angleydzp); + } else if (type == "TwistedTrap") { // shape constructor parameters double PhiTwist = 0; double ZHalfLength = 0.; @@ -1891,567 +2228,647 @@ GeoShape* ReadGeoModel::buildShape(const unsigned int shapeId, type_shapes_boole double DX4HalfLength = 0.; double DTiltAngleAlpha = 0.; // get parameters - for( auto& par : shapePars) { + for (auto& par : shapePars) { + std::vector<std::string> vars = splitString(par, '='); + std::string varName = vars[0]; + std::string varValue = vars[1]; + if (varName == "PhiTwist") PhiTwist = std::stod(varValue); // angle + if (varName == "ZHalfLength") + ZHalfLength = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "Theta") Theta = std::stod(varValue); // angle + if (varName == "Phi") Phi = std::stod(varValue); // angle + if (varName == "DY1HalfLength") + DY1HalfLength = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "DX1HalfLength") + DX1HalfLength = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "DX2HalfLength") + DX2HalfLength = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "DY2HalfLength") + DY2HalfLength = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "DX3HalfLength") + DX3HalfLength = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "DX4HalfLength") + DX4HalfLength = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "DTiltAngleAlpha") + DTiltAngleAlpha = std::stod(varValue); // angle + } + shape = + new GeoTwistedTrap(PhiTwist, ZHalfLength, Theta, Phi, DY1HalfLength, + DX1HalfLength, DX2HalfLength, DY2HalfLength, + DX3HalfLength, DX4HalfLength, DTiltAngleAlpha); + } else if (type == "Trd") { + // shape constructor parameters + double XHalfLength1 = 0.; + double XHalfLength2 = 0.; + double YHalfLength1 = 0.; + double YHalfLength2 = 0.; + double ZHalfLength = 0.; + // get parameters + for (auto& par : shapePars) { + std::vector<std::string> vars = splitString(par, '='); + std::string varName = vars[0]; + std::string varValue = vars[1]; + // std::cout << "varValue:" << varValue; + if (varName == "XHalfLength1") + XHalfLength1 = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "XHalfLength2") + XHalfLength2 = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "YHalfLength1") + YHalfLength1 = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "YHalfLength2") + YHalfLength2 = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "ZHalfLength") + ZHalfLength = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + } + shape = new GeoTrd(XHalfLength1, XHalfLength2, YHalfLength1, + YHalfLength2, ZHalfLength); + } else if (type == "Tube") { + // shape parameters + double RMin = 0.; + double RMax = 0.; + double ZHalfLength = 0.; + // get parameters + for (auto& par : shapePars) { + std::vector<std::string> vars = splitString(par, '='); + std::string varName = vars[0]; + std::string varValue = vars[1]; + if (varName == "RMin") + RMin = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "RMax") + RMax = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "ZHalfLength") + ZHalfLength = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + } + shape = new GeoTube(RMin, RMax, ZHalfLength); + } else if (type == "Tubs") { + // shape parameters + double RMin = 0.; + double RMax = 0.; + double ZHalfLength = 0.; + double SPhi = 0.; + double DPhi = 0.; + // get parameters + for (auto& par : shapePars) { + std::vector<std::string> vars = splitString(par, '='); + std::string varName = vars[0]; + std::string varValue = vars[1]; + if (varName == "RMin") + RMin = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "RMax") + RMax = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "ZHalfLength") + ZHalfLength = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "SPhi") + SPhi = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + if (varName == "DPhi") + DPhi = std::stod(varValue); // * SYSTEM_OF_UNITS::mm; + } + shape = new GeoTubs(RMin, RMax, ZHalfLength, SPhi, DPhi); + } else if (type == "Shift") { + // shape parameters + unsigned int shapeOpId = 0; + unsigned int transfId = 0; + // get parameters + for (auto& par : shapePars) { + std::vector<std::string> vars = splitString(par, '='); + std::string varName = vars[0]; + std::string varValue = vars[1]; + if (varName == "A") shapeOpId = std::stoi(varValue); + if (varName == "X") transfId = std::stoi(varValue); + } + if (shapeOpId == 0 || transfId == 0) { + std::cout << "ERROR! Shift shape - input operand shapes' IDs are " + "empty! (shapeId: " + << shapeOpId << ", transfId:" << transfId << ")" + << std::endl; + exit(EXIT_FAILURE); + } + + // if both operands are built already, + // then get them from cache, + // and build the operator shape with them, + if (isBuiltShape(shapeOpId) && isBuiltTransform(transfId)) { + const GeoShape* shapeOp = getBuiltShape(shapeOpId); + const GeoTransform* transf = getBuiltTransform(transfId); + // TODO: here we create a fake GeoTransform to get a + // GeoTrf::Transform3D. + // TODO: ==> Perhaps we could keep a table for bare + // GeoTrf::Transform3D transforms used in GeoShift nodes. + GeoTrf::Transform3D transfX = transf->getTransform(); + transf->unref(); // delete the transf from the heap, because we + // don't need the node, only the bare + // transformation matrix + GeoShapeShift* shapeNew = new GeoShapeShift(shapeOp, transfX); + storeBuiltShape(shapeId, shapeNew); + shape = shapeNew; + } + // otherwise, build the operands + else { + // TODO: IMPORTANT!!! --> check how the transf used in shift are + // saved into the DB, because they are bare transf and not + // GeoTransform nodes... + + // first, check if the transform is built; + // if so, use that; + // if not, build the transform + + // get the referenced Transform, then get the bare transform matrix + // from it + GeoTransform* transf = nullptr; + GeoTrf::Transform3D transfX; + if (isBuiltTransform(transfId)) { + transf = getBuiltTransform(transfId); + } else { + transf = buildTransform(transfId); + } + // TODO: here we create a fake GeoTransform to get a + // GeoTrf::Transform3D. + // TODO: ==> Perhaps we could keep a table for bare + // GeoTrf::Transform3D transforms used in GeoShift nodes. + transfX = transf->getTransform(); + transf->unref(); // delete the transf from the heap, because we + // don't need the node, only the bare + // transformation matrix + + // then, check the type of the operand shape + bool isAOperator = isShapeOperator(shapeOpId); + + // if operand shape is simple/actual shape (i.e., not + // boolean/operator), then build it, then build the boolean shape + // with that + if (!isAOperator) { + const GeoShape* shapeOp = + buildShape(shapeOpId, shapes_info_sub); + + if (shapeOp == nullptr || transf == nullptr) { + std::cout << "ERROR!!! Shift - shapeOp or transfX are " + "NULL! Exiting..." + << std::endl; + exit(EXIT_FAILURE); + } + GeoShapeShift* shapeNew = new GeoShapeShift(shapeOp, transfX); + shape = shapeNew; + } + // ...otherwise, build the Shift operator shape without operands + // and save the needed pieces of information to build the actual + // operands and shape later. + else { + GeoShapeShift* shapeNew = new GeoShapeShift(); + tuple_shapes_boolean_info tt(shapeId, shapeNew, shapeOpId, + transfId); + shapes_info_sub->push_back( + tt); //! Push the information about the new boolean shape + //! at the end of the very same container we are + //! iterating over + shape = shapeNew; + } + } + } else if (type == "Subtraction" || type == "Union" || + type == "Intersection") { + // Check what shapes are subtracted/united/intersected: + // - If they are actual shapes, build them and return + // - If they are boolean/operator shapes, then store the shape for later + // and continue + + // shape's operands + unsigned int opA = 0; + unsigned int opB = 0; + // get parameters + for (auto& par : shapePars) { std::vector<std::string> vars = splitString(par, '='); std::string varName = vars[0]; std::string varValue = vars[1]; - if (varName == "PhiTwist") PhiTwist = std::stod(varValue);// angle - if (varName == "ZHalfLength") ZHalfLength = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "Theta") Theta = std::stod(varValue); // angle - if (varName == "Phi") Phi = std::stod(varValue); // angle - if (varName == "DY1HalfLength") DY1HalfLength = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "DX1HalfLength") DX1HalfLength = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "DX2HalfLength") DX2HalfLength = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "DY2HalfLength") DY2HalfLength = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "DX3HalfLength") DX3HalfLength = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "DX4HalfLength") DX4HalfLength = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "DTiltAngleAlpha")DTiltAngleAlpha = std::stod(varValue);//angle + if (varName == "opA") opA = std::stoi(varValue); + if (varName == "opB") opB = std::stoi(varValue); } - shape = new GeoTwistedTrap (PhiTwist, ZHalfLength, Theta, Phi, DY1HalfLength, DX1HalfLength, DX2HalfLength, DY2HalfLength, DX3HalfLength, DX4HalfLength, DTiltAngleAlpha); - } - else if (type == "Trd") { - // shape constructor parameters - double XHalfLength1 = 0.; - double XHalfLength2 = 0.; - double YHalfLength1 = 0.; - double YHalfLength2 = 0.; - double ZHalfLength = 0.; - // get parameters - for( auto& par : shapePars) { - std::vector<std::string> vars = splitString(par, '='); - std::string varName = vars[0]; - std::string varValue = vars[1]; - // std::cout << "varValue:" << varValue; - if (varName == "XHalfLength1") XHalfLength1 = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "XHalfLength2") XHalfLength2 = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "YHalfLength1") YHalfLength1 = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "YHalfLength2") YHalfLength2 = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "ZHalfLength") ZHalfLength = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - } - shape = new GeoTrd (XHalfLength1, XHalfLength2, YHalfLength1, YHalfLength2, ZHalfLength); - } - else if (type == "Tube") { - // shape parameters - double RMin = 0.; - double RMax = 0.; - double ZHalfLength = 0.; - // get parameters - for( auto& par : shapePars) { - std::vector<std::string> vars = splitString(par, '='); - std::string varName = vars[0]; - std::string varValue = vars[1]; - if (varName == "RMin") RMin = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "RMax") RMax = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "ZHalfLength") ZHalfLength = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - } - shape = new GeoTube(RMin, RMax, ZHalfLength); - } - else if (type == "Tubs") { - // shape parameters - double RMin = 0.; - double RMax = 0.; - double ZHalfLength = 0.; - double SPhi = 0.; - double DPhi = 0.; - // get parameters - for( auto& par : shapePars) { - std::vector<std::string> vars = splitString(par, '='); - std::string varName = vars[0]; - std::string varValue = vars[1]; - if (varName == "RMin") RMin = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "RMax") RMax = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "ZHalfLength") ZHalfLength = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "SPhi") SPhi = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - if (varName == "DPhi") DPhi = std::stod(varValue);// * SYSTEM_OF_UNITS::mm; - } - shape = new GeoTubs (RMin, RMax, ZHalfLength, SPhi, DPhi); - } - else if (type == "Shift") { - // shape parameters - unsigned int shapeOpId = 0; - unsigned int transfId = 0; - // get parameters - for( auto& par : shapePars) { - std::vector<std::string> vars = splitString(par, '='); - std::string varName = vars[0]; - std::string varValue = vars[1]; - if (varName == "A") shapeOpId = std::stoi(varValue); - if (varName == "X") transfId = std::stoi(varValue); - } - if (shapeOpId == 0 || transfId == 0) { - std::cout << "ERROR! Shift shape - input operand shapes' IDs are empty! (shapeId: " << shapeOpId << ", transfId:" << transfId << ")" << std::endl; - exit(EXIT_FAILURE); - } - - // if both operands are built already, - // then get them from cache, - // and build the operator shape with them, - if ( isBuiltShape(shapeOpId) && isBuiltTransform(transfId) ) { - const GeoShape* shapeOp = getBuiltShape(shapeOpId); - const GeoTransform* transf = getBuiltTransform(transfId); - // TODO: here we create a fake GeoTransform to get a GeoTrf::Transform3D. - // TODO: ==> Perhaps we could keep a table for bare GeoTrf::Transform3D transforms used in GeoShift nodes. - GeoTrf::Transform3D transfX = transf->getTransform(); - transf->unref(); // delete the transf from the heap, because we don't need the node, only the bare transformation matrix - GeoShapeShift* shapeNew = new GeoShapeShift(shapeOp, transfX); - storeBuiltShape(shapeId, shapeNew); - shape = shapeNew; - } - // otherwise, build the operands - else { - - // TODO: IMPORTANT!!! --> check how the transf used in shift are saved into the DB, because they are bare transf and not GeoTransform nodes... - - // first, check if the transform is built; - // if so, use that; - // if not, build the transform - - // get the referenced Transform, then get the bare transform matrix from it - GeoTransform* transf = nullptr; - GeoTrf::Transform3D transfX; - if (isBuiltTransform(transfId)) { - transf = getBuiltTransform(transfId); - } else { - transf = buildTransform(transfId); - } - // TODO: here we create a fake GeoTransform to get a GeoTrf::Transform3D. - // TODO: ==> Perhaps we could keep a table for bare GeoTrf::Transform3D transforms used in GeoShift nodes. - transfX = transf->getTransform(); - transf->unref(); // delete the transf from the heap, because we don't need the node, only the bare transformation matrix - - // then, check the type of the operand shape - bool isAOperator = isShapeOperator( shapeOpId ); - - // if operand shape is simple/actual shape (i.e., not boolean/operator), - // then build it, - // then build the boolean shape with that - if ( !isAOperator ) { - const GeoShape* shapeOp = buildShape( shapeOpId, shapes_info_sub ); - - if ( shapeOp == nullptr || transf == nullptr ) { - std::cout << "ERROR!!! Shift - shapeOp or transfX are NULL! Exiting..." << std::endl; - exit(EXIT_FAILURE); - } - GeoShapeShift* shapeNew = new GeoShapeShift(shapeOp, transfX); - shape = shapeNew; - } - // ...otherwise, build the Shift operator shape without operands - // and save the needed pieces of information to build the actual - // operands and shape later. - else { - GeoShapeShift* shapeNew = new GeoShapeShift(); - tuple_shapes_boolean_info tt (shapeId, shapeNew, shapeOpId, transfId); - shapes_info_sub->push_back(tt); //! Push the information about the new boolean shape at the end of the very same container we are iterating over - shape = shapeNew; - } - } - } - else if (type == "Subtraction" || type == "Union" || type == "Intersection") { - - // Check what shapes are subtracted/united/intersected: - // - If they are actual shapes, build them and return - // - If they are boolean/operator shapes, then store the shape for later and continue - - // shape's operands - unsigned int opA = 0; - unsigned int opB = 0; - // get parameters - for( auto& par : shapePars) { - std::vector<std::string> vars = splitString(par, '='); - std::string varName = vars[0]; - std::string varValue = vars[1]; - if (varName == "opA") opA = std::stoi(varValue); - if (varName == "opB") opB = std::stoi(varValue); - } - if (opA == 0 || opB == 0) { - std::cout << "ERROR! Subtraction/Union/Intersection shape - input operand shapes' IDs are empty! (opA: " << opA << ", opB:" << opB << ")" << std::endl; - exit(EXIT_FAILURE); - } - - // if both operands are built already, - // then get them from cache, - // and build the operator with them - if ( isBuiltShape(opA) && isBuiltShape(opB) ) { - // std::cout << "both operand shapes are built, build the operator shape..." << std::endl; - GeoShape* shapeNew = nullptr; - const GeoShape* shapeA = getBuiltShape(opA); - const GeoShape* shapeB = getBuiltShape(opB); - if ("Subtraction" == type) { - shapeNew = new GeoShapeSubtraction(shapeA, shapeB); + if (opA == 0 || opB == 0) { + std::cout << "ERROR! Subtraction/Union/Intersection shape - input " + "operand shapes' IDs are empty! (opA: " + << opA << ", opB:" << opB << ")" << std::endl; + exit(EXIT_FAILURE); } - else if ("Union" == type) { - shapeNew = new GeoShapeUnion(shapeA, shapeB); - } - else if ("Intersection" == type) { - shapeNew = new GeoShapeIntersection(shapeA, shapeB); - } - shape = shapeNew; - } - // otherwise, build the operand shapes... - else { - // first check the operands' type - bool isAOperator = isShapeOperator( opA ); - bool isBOperator = isShapeOperator( opB ); - - // if both are simple/actual shapes (i.e., not booleans), - // then build them, then build the boolean shape with them, and store that. - if ( !isAOperator && !isBOperator) { - const GeoShape* shapeA = buildShape( opA, shapes_info_sub ); - const GeoShape* shapeB = buildShape( opB, shapes_info_sub ); - if ( shapeA == NULL || shapeB == NULL ) { - std::cout << "ERROR!!! shapeA or shapeB are NULL!" << std::endl; - exit(EXIT_FAILURE); + // if both operands are built already, + // then get them from cache, + // and build the operator with them + if (isBuiltShape(opA) && isBuiltShape(opB)) { + // std::cout << "both operand shapes are built, build the operator + // shape..." << std::endl; + GeoShape* shapeNew = nullptr; + const GeoShape* shapeA = getBuiltShape(opA); + const GeoShape* shapeB = getBuiltShape(opB); + if ("Subtraction" == type) { + shapeNew = new GeoShapeSubtraction(shapeA, shapeB); + } else if ("Union" == type) { + shapeNew = new GeoShapeUnion(shapeA, shapeB); + } else if ("Intersection" == type) { + shapeNew = new GeoShapeIntersection(shapeA, shapeB); + } + shape = shapeNew; } + // otherwise, build the operand shapes... + else { + // first check the operands' type + bool isAOperator = isShapeOperator(opA); + bool isBOperator = isShapeOperator(opB); + + // if both are simple/actual shapes (i.e., not booleans), + // then build them, then build the boolean shape with them, and + // store that. + if (!isAOperator && !isBOperator) { + const GeoShape* shapeA = buildShape(opA, shapes_info_sub); + const GeoShape* shapeB = buildShape(opB, shapes_info_sub); + if (shapeA == NULL || shapeB == NULL) { + std::cout << "ERROR!!! shapeA or shapeB are NULL!" + << std::endl; + exit(EXIT_FAILURE); + } + + GeoShape* shapeNew = nullptr; + if ("Subtraction" == type) { + shapeNew = new GeoShapeSubtraction(shapeA, shapeB); + } else if ("Union" == type) { + shapeNew = new GeoShapeUnion(shapeA, shapeB); + } else if ("Intersection" == type) { + shapeNew = new GeoShapeIntersection(shapeA, shapeB); + } + + shape = shapeNew; + } + // ...otherwise, build the Subtraction operator shape without + // operands and save the needed pieces of information to build the + // actual operands and shape later. + else { + GeoShape* shapeNew = nullptr; + if ("Subtraction" == type) { + shapeNew = new GeoShapeSubtraction; + } else if ("Union" == type) { + shapeNew = new GeoShapeUnion; + } else if ("Intersection" == type) { + shapeNew = new GeoShapeIntersection; + } - GeoShape* shapeNew = nullptr; - if ("Subtraction" == type) { - shapeNew = new GeoShapeSubtraction(shapeA, shapeB); + tuple_shapes_boolean_info tt(shapeId, shapeNew, opA, opB); + shapes_info_sub->push_back( + tt); //! Push the information about the new boolean shape + //! at the end of the very same container we are + //! iterating over + + shape = shapeNew; + } } - else if ("Union" == type) { - shapeNew = new GeoShapeUnion(shapeA, shapeB); + } + // LAr custom shape + else if (type == "CustomShape") { + std::string name = ""; + // check parameters + // this complex test is needed to handle null strings in the DB records + bool okPars = false; + for (auto& par : shapePars) { + std::string str = + par.substr(par.find("=")); // get from "=" to the end + if (str.size() > 0) okPars = true; } - else if ("Intersection" == type) { - shapeNew = new GeoShapeIntersection(shapeA, shapeB); + // if ( shapePars.size() > 0 && ((shapePars.filter("=")).size() > 0) ) + // // this complex test is needed to handle null strings + if (shapePars.size() > 0 && okPars) { + // get parameters + for (auto& par : shapePars) { + std::vector<std::string> vars = splitString(par, '='); + std::string varName = vars[0]; + std::string varValue = vars[1]; + if (varName == "name") name = varValue; + } + } else { + muxCout.lock(); + // throw std::invalid_argument("CustomShape parameters' list is + // empty!!"); + std::cout + << "ERROR!!! --> CustomShape parameters' list is empty!! It " + "seems the geometry file you are running on is corrupted." + << std::endl; + muxCout.unlock(); + exit(EXIT_FAILURE); } + shape = new GeoUnidentifiedShape("LArCustomShape", name); + } else if (type == "UnidentifiedShape") { + std::string name = ""; + std::string asciiData = ""; - shape = shapeNew; - } - // ...otherwise, build the Subtraction operator shape without operands - // and save the needed pieces of information to build the actual - // operands and shape later. - else { - GeoShape* shapeNew = nullptr; - if ( "Subtraction" == type ) { - shapeNew = new GeoShapeSubtraction; - } else if ( "Union" == type ) { - shapeNew = new GeoShapeUnion; - } else if ( "Intersection" == type ) { - shapeNew = new GeoShapeIntersection; - } + // debug + muxCout.lock(); + if (m_loglevel >= 2) + std::cout + << "GeoModelRead - loading 'UnidentifiedShape' - parameters: " + << parameters << std::endl; + muxCout.unlock(); - tuple_shapes_boolean_info tt (shapeId, shapeNew, opA, opB); - shapes_info_sub->push_back(tt); //! Push the information about the new boolean shape at the end of the very same container we are iterating over - - shape = shapeNew; - } - } - } - //LAr custom shape - else if(type == "CustomShape") { - std::string name = ""; - // check parameters - // this complex test is needed to handle null strings in the DB records - bool okPars = false; - for( auto& par : shapePars) { - std::string str = par.substr( par.find("=") ); // get from "=" to the end - if (str.size() > 0) okPars = true; - } - //if ( shapePars.size() > 0 && ((shapePars.filter("=")).size() > 0) ) // this complex test is needed to handle null strings - if ( shapePars.size() > 0 && okPars ) - { - // get parameters - for( auto& par : shapePars) { - std::vector<std::string> vars = splitString(par, '='); - std::string varName = vars[0]; - std::string varValue = vars[1]; - if (varName == "name") name = varValue; - } - } else { - muxCout.lock(); - // throw std::invalid_argument("CustomShape parameters' list is empty!!"); - std::cout << "ERROR!!! --> CustomShape parameters' list is empty!! It seems the geometry file you are running on is corrupted." << std::endl; - muxCout.unlock(); - exit(EXIT_FAILURE); - } - shape = new GeoUnidentifiedShape("LArCustomShape",name); - } - else if (type=="UnidentifiedShape") { - std::string name = ""; - std::string asciiData = ""; - - // debug - muxCout.lock(); - if (m_deepDebug) std::cout << "GeoModelRead - loading 'UnidentifiedShape' - parameters: " << parameters << std::endl; - muxCout.unlock(); - - // check parameters - // this complex test is needed to handle null strings in the DB records - bool okPars = false; - for( auto& par : shapePars) { - std::string str = par.substr( par.find("=") ); // get from "=" to the end - if (str.size() > 0) okPars = true; - } - if ( shapePars.size() > 0 && okPars ) - { - // get parameters - for( auto& par : shapePars) { - - // debug + // check parameters + // this complex test is needed to handle null strings in the DB records + bool okPars = false; + for (auto& par : shapePars) { + std::string str = + par.substr(par.find("=")); // get from "=" to the end + if (str.size() > 0) okPars = true; + } + if (shapePars.size() > 0 && okPars) { + // get parameters + for (auto& par : shapePars) { + // debug + muxCout.lock(); + if (m_loglevel >= 2) + std::cout + << "GeoModelRead - loading 'UnidentifiedShape' - par: " + << par << std::endl; + muxCout.unlock(); + + std::vector<std::string> vars = splitString(par, '='); + if (vars.size() > 1) { + std::string varName = vars[0]; + std::string varValue = vars[1]; + if (varName == "name") name = varValue; + if (varName == "asciiData") asciiData = varValue; + } else { + okPars = false; + } + } + } else { + okPars = false; + } + if (!okPars) { + // throw std::invalid_argument("UnidentifiedShape parameters' list + // is empty!!"); muxCout.lock(); - if (m_deepDebug) std::cout << "GeoModelRead - loading 'UnidentifiedShape' - par: " << par << std::endl; + std::cout << "\n\n\tERROR!!! --> UnidentifiedShape is not properly " + "defined!! It seems the geometry file you are running " + "on is corrupted." + << std::endl; + std::cout + << "\tINFO --> UnidentifiedShape should be defined from two " + "strings: a string defining its type/name; and a ASCII data " + "string defining its parameters. The latter can be set to " + "an empty string if not used/needed." + << std::endl; + std::cout << "\tINFO --> UnidentifiedShape parameters' list is " + "empty or one datum is missing!! --> parameters: " + << parameters << std::endl; + std::cout << "\tINFO --> parameters: " << parameters << std::endl + << std::endl; muxCout.unlock(); - - std::vector<std::string> vars = splitString(par, '='); - if (vars.size() > 1) { - std::string varName = vars[0]; - std::string varValue = vars[1]; - if (varName == "name") name = varValue; - if (varName == "asciiData") asciiData = varValue; - } else { - okPars = false; - } + std::runtime_error( + "UnidentifiedShape parameters' list are empty or incomplete!!"); } + shape = new GeoUnidentifiedShape(name, asciiData); + } else { - okPars = false; - } - if ( !okPars ) { - // throw std::invalid_argument("UnidentifiedShape parameters' list is empty!!"); - muxCout.lock(); - std::cout << "\n\n\tERROR!!! --> UnidentifiedShape is not properly defined!! It seems the geometry file you are running on is corrupted." << std::endl; - std::cout << "\tINFO --> UnidentifiedShape should be defined from two strings: a string defining its type/name; and a ASCII data string defining its parameters. The latter can be set to an empty string if not used/needed." << std::endl; - std::cout << "\tINFO --> UnidentifiedShape parameters' list is empty or one datum is missing!! --> parameters: " << parameters << std::endl; - std::cout << "\tINFO --> parameters: " << parameters << std::endl << std::endl; - muxCout.unlock(); - std::runtime_error("UnidentifiedShape parameters' list are empty or incomplete!!"); + m_unknown_shapes.insert( + type); // save unknwon shapes for later warning message + shape = buildDummyShape(); } - shape = new GeoUnidentifiedShape(name,asciiData); - - } - else { - m_unknown_shapes.insert(type); // save unknwon shapes for later warning message - shape = buildDummyShape(); - } - - //! store into the cache the shape we have just built, - //! for later use when referenced by another node - storeBuiltShape(shapeId, shape); - return shape; // FIXME: do we still need the return? probably not, because we now store all the shapes that have been built in this method + //! store into the cache the shape we have just built, + //! for later use when referenced by another node + storeBuiltShape(shapeId, shape); -// } - -// catch (std::invalid_argument& e) -// { -// std::cerr << e.what() << std::endl; -// exit(EXIT_FAILURE); -// } + return shape; // FIXME: do we still need the return? probably not, because + // we now store all the shapes that have been built in this + // method + // } + // catch (std::invalid_argument& e) + // { + // std::cerr << e.what() << std::endl; + // exit(EXIT_FAILURE); + // } } - - // TODO: move to an untilities file/class -void printTuple(tuple_shapes_boolean_info tuple) -{ - std::apply([](auto&&... args) { ( (std::cout << args << ", "), ...); }, tuple); // needs C++17 - std::cout << std::endl; +void printTuple(tuple_shapes_boolean_info tuple) { + std::apply([](auto&&... args) { ((std::cout << args << ", "), ...); }, + tuple); // needs C++17 + std::cout << std::endl; } // TODO: move to an untilities file/class -void inspectListShapesToBuild(type_shapes_boolean_info list) -{ - for (auto tuple : list) { - printTuple(tuple); - std::cout << std::endl; - } +void inspectListShapesToBuild(type_shapes_boolean_info list) { + for (auto tuple : list) { + printTuple(tuple); + std::cout << std::endl; + } } +void ReadGeoModel::createBooleanShapeOperands( + type_shapes_boolean_info* shapes_info_sub) { + if (shapes_info_sub->size() == 0) return; -void ReadGeoModel::createBooleanShapeOperands(type_shapes_boolean_info* shapes_info_sub) -{ - if (shapes_info_sub->size() == 0) return; - - // debug - // std::cout << "\ncreateBooleanShapeOperands() - start..." << std::endl; - // inspectListShapesToBuild(shapes_info_sub); - - // Iterate over the list. The size may be incremented while iterating (therefore, we cannot use iterators) - for (type_shapes_boolean_info::size_type ii = 0; ii < shapes_info_sub->size(); ++ii) - { - // get the tuple containing the data about the operand shapes to build - tuple_shapes_boolean_info tuple = (*shapes_info_sub)[ii]; - // std::cout << "tuple: "; printTuple(tuple); // debug - - // Initializing variables for unpacking - unsigned int shapeID = 0; //std::get<0>(tuple); - GeoShape* boolShPtr = nullptr; //std::get<1>(tuple); - unsigned int idA = 0; //std::get<2>(tuple); - unsigned int idB = 0; //std::get<3>(tuple); - - // use 'tie' to unpack the tuple values into separate variables - std::tie(shapeID, boolShPtr, idA, idB) = tuple; - - if (shapeID == 0 || boolShPtr == nullptr || idA == 0 || idB == 0) { - muxCout.lock(); - std::cout << "ERROR! Boolean/Operator shape - shape is NULL or operands' IDs are not defined! (shapeID: " << shapeID << ", idA: " << idA << ", idB:" << idB << ")" << std::endl; - muxCout.unlock(); - exit(EXIT_FAILURE); - } - - if (isShapeBoolean(shapeID)) { - - GeoShape* shapeA = nullptr; - GeoShape* shapeB = nullptr; - - // if both operands are built already... - if ( isBuiltShape(idA) && isBuiltShape(idB) ) { - // then build the operator shape... - shapeA = getBuiltShape(idA); - shapeB = getBuiltShape(idB); //TODO: customize for Shift as well - } else { - // otherwise, build the operand shapes - shapeA = getBooleanReferencedShape(idA, shapes_info_sub); - shapeB = getBooleanReferencedShape(idB, shapes_info_sub); - } - // Now, assign the new shapes to the boolean shape we're building - if (dynamic_cast<GeoShapeIntersection*>(boolShPtr)) { - GeoShapeIntersection* ptr = dynamic_cast<GeoShapeIntersection*>(boolShPtr); - ptr->m_opA = shapeA; - ptr->m_opB = shapeB; - ptr->m_opA->ref(); - ptr->m_opB->ref(); - } - else if (dynamic_cast<GeoShapeSubtraction*>(boolShPtr)) { - GeoShapeSubtraction* ptr = dynamic_cast<GeoShapeSubtraction*>(boolShPtr); - ptr->m_opA = shapeA; - ptr->m_opB = shapeB; - ptr->m_opA->ref(); - ptr->m_opB->ref(); - } - else if (dynamic_cast<GeoShapeUnion*>(boolShPtr)) { - GeoShapeUnion* ptr = dynamic_cast<GeoShapeUnion*>(boolShPtr); - ptr->m_opA = shapeA; - ptr->m_opB = shapeB; - ptr->m_opA->ref(); - ptr->m_opB->ref(); - } - else{ - // TODO: move to standard error message for all instances - std::cout << "ERROR!!! shape is not boolean/operator! Write to 'geomodel-developers@cern.ch'. Exiting..." << std::endl; - exit(EXIT_FAILURE); + // debug + // std::cout << "\ncreateBooleanShapeOperands() - start..." << + // std::endl; inspectListShapesToBuild(shapes_info_sub); + + // Iterate over the list. The size may be incremented while iterating + // (therefore, we cannot use iterators) + for (type_shapes_boolean_info::size_type ii = 0; + ii < shapes_info_sub->size(); ++ii) { + // get the tuple containing the data about the operand shapes to + // build + tuple_shapes_boolean_info tuple = (*shapes_info_sub)[ii]; + // std::cout << "tuple: "; printTuple(tuple); // debug + + // Initializing variables for unpacking + unsigned int shapeID = 0; // std::get<0>(tuple); + GeoShape* boolShPtr = nullptr; // std::get<1>(tuple); + unsigned int idA = 0; // std::get<2>(tuple); + unsigned int idB = 0; // std::get<3>(tuple); + + // use 'tie' to unpack the tuple values into separate variables + std::tie(shapeID, boolShPtr, idA, idB) = tuple; + + if (shapeID == 0 || boolShPtr == nullptr || idA == 0 || idB == 0) { + muxCout.lock(); + std::cout << "ERROR! Boolean/Operator shape - shape is NULL or " + "operands' IDs are not defined! (shapeID: " + << shapeID << ", idA: " << idA << ", idB:" << idB << ")" + << std::endl; + muxCout.unlock(); + exit(EXIT_FAILURE); } - } else if ("Shift" == getShapeType(shapeID)) { - GeoShape* opShape = nullptr; - GeoTrf::Transform3D shiftX; - GeoTransform* shiftTransf = nullptr; // TODO: remove the need for a temp GeoTransform, store the bare transforms as well... + if (isShapeBoolean(shapeID)) { + GeoShape* shapeA = nullptr; + GeoShape* shapeB = nullptr; - // if both operands are built already... - if ( isBuiltShape(idA) && isBuiltTransform(idB) ) { - // then build the operator shape... - opShape = getBuiltShape(idA); - shiftTransf = getBuiltTransform(idB); + // if both operands are built already... + if (isBuiltShape(idA) && isBuiltShape(idB)) { + // then build the operator shape... + shapeA = getBuiltShape(idA); + shapeB = + getBuiltShape(idB); // TODO: customize for Shift as well + } else { + // otherwise, build the operand shapes + shapeA = getBooleanReferencedShape(idA, shapes_info_sub); + shapeB = getBooleanReferencedShape(idB, shapes_info_sub); + } + // Now, assign the new shapes to the boolean shape we're + // building + if (dynamic_cast<GeoShapeIntersection*>(boolShPtr)) { + GeoShapeIntersection* ptr = + dynamic_cast<GeoShapeIntersection*>(boolShPtr); + ptr->m_opA = shapeA; + ptr->m_opB = shapeB; + ptr->m_opA->ref(); + ptr->m_opB->ref(); + } else if (dynamic_cast<GeoShapeSubtraction*>(boolShPtr)) { + GeoShapeSubtraction* ptr = + dynamic_cast<GeoShapeSubtraction*>(boolShPtr); + ptr->m_opA = shapeA; + ptr->m_opB = shapeB; + ptr->m_opA->ref(); + ptr->m_opB->ref(); + } else if (dynamic_cast<GeoShapeUnion*>(boolShPtr)) { + GeoShapeUnion* ptr = dynamic_cast<GeoShapeUnion*>(boolShPtr); + ptr->m_opA = shapeA; + ptr->m_opB = shapeB; + ptr->m_opA->ref(); + ptr->m_opB->ref(); + } else { + // TODO: move to standard error message for all instances + std::cout << "ERROR!!! shape is not boolean/operator! Write to " + "'geomodel-developers@cern.ch'. Exiting..." + << std::endl; + exit(EXIT_FAILURE); + } + } else if ("Shift" == getShapeType(shapeID)) { + GeoShape* opShape = nullptr; + GeoTrf::Transform3D shiftX; + GeoTransform* shiftTransf = + nullptr; // TODO: remove the need for a temp GeoTransform, + // store the bare transforms as well... + + // if both operands are built already... + if (isBuiltShape(idA) && isBuiltTransform(idB)) { + // then build the operator shape... + opShape = getBuiltShape(idA); + shiftTransf = getBuiltTransform(idB); + } else { + // otherwise, build the operand shapes + opShape = getBooleanReferencedShape(idA, shapes_info_sub); + shiftTransf = buildTransform(idB); + } + shiftX = shiftTransf->getTransform(); + shiftTransf->unref(); // delete from heap, we only needed to get + // the bare transform // TODO: remove that + // need, store the bare transforms as well... + + if (dynamic_cast<GeoShapeShift*>(boolShPtr)) { + GeoShapeShift* ptr = dynamic_cast<GeoShapeShift*>(boolShPtr); + ptr->m_op = opShape; + ptr->m_shift = shiftX; + ptr->m_op->ref(); + } else { + std::cout + << "ERROR!!! shape is not a Shift operator! Exiting..." + << std::endl; + exit(EXIT_FAILURE); + } } else { - // otherwise, build the operand shapes - opShape = getBooleanReferencedShape(idA, shapes_info_sub); - shiftTransf = buildTransform(idB); - } - shiftX = shiftTransf->getTransform(); - shiftTransf->unref(); // delete from heap, we only needed to get the bare transform // TODO: remove that need, store the bare transforms as well... - - if (dynamic_cast<GeoShapeShift*>(boolShPtr)) { - GeoShapeShift* ptr = dynamic_cast<GeoShapeShift*>(boolShPtr); - ptr->m_op = opShape; - ptr->m_shift = shiftX; - ptr->m_op->ref(); + std::cout << "ERROR! Undefined operator shape! This part of the " + "code should not be reached! Exiting..." + << std::endl; + exit(EXIT_FAILURE); } - else { - std::cout << "ERROR!!! shape is not a Shift operator! Exiting..." << std::endl; - exit(EXIT_FAILURE); - } - } else { - std::cout << "ERROR! Undefined operator shape! This part of the code should not be reached! Exiting..." << std::endl; - exit(EXIT_FAILURE); - } - // then, store the now completed shape and continue to the next item - storeBuiltShape(shapeID, boolShPtr); - } + // then, store the now completed shape and continue to the next item + storeBuiltShape(shapeID, boolShPtr); + } } - - -GeoShape* ReadGeoModel::getBooleanReferencedShape(const unsigned int shapeID, type_shapes_boolean_info* shapes_info_sub) -{ - if (0 == shapeID) { - std::cout << "ERROR!! ShapeID = 0!" << std::endl; - exit(EXIT_FAILURE); - } - - GeoShape* shape; - // if A is built already, then take it from cache - if (isBuiltShape(shapeID)) { - if (m_deepDebug) std::cout << "operandA is built, taking it from cache..." << std::endl; // debug - shape = getBuiltShape(shapeID); - } else { - // if not built and not a boolean shape, then build it - if (!isShapeOperator(shapeID)) { - if (m_deepDebug) std::cout << "operandA is not built and not an operator, build it..." << std::endl; // debug - shape = buildShape( shapeID, shapes_info_sub ); - if ( shape == NULL ) { - std::cout << "ERROR!!! shape is NULL!" << std::endl; +GeoShape* ReadGeoModel::getBooleanReferencedShape( + const unsigned int shapeID, type_shapes_boolean_info* shapes_info_sub) { + if (0 == shapeID) { + std::cout << "ERROR!! ShapeID = 0!" << std::endl; exit(EXIT_FAILURE); - } } - // if A is a boolean shape, then create an empty shape, - // store it for later completion, and use that - else { - if (m_deepDebug) std::cout << "operandA is not built and it is an operator, add it to build it later..." << std::endl; // debug - shape = addEmptyBooleanShapeForCompletion(shapeID, shapes_info_sub); - } - } -// inspectListShapesToBuild(m_shapes_info_sub); // debug - return shape; -} + GeoShape* shape; + // if A is built already, then take it from cache + if (isBuiltShape(shapeID)) { + if (m_loglevel >= 2) + std::cout << "operandA is built, taking it from cache..." + << std::endl; // debug + shape = getBuiltShape(shapeID); + } else { + // if not built and not a boolean shape, then build it + if (!isShapeOperator(shapeID)) { + if (m_loglevel >= 2) + std::cout << "operandA is not built and not an operator, " + "build it..." + << std::endl; // debug + shape = buildShape(shapeID, shapes_info_sub); + if (shape == NULL) { + std::cout << "ERROR!!! shape is NULL!" << std::endl; + exit(EXIT_FAILURE); + } + } + // if A is a boolean shape, then create an empty shape, + // store it for later completion, and use that + else { + if (m_loglevel >= 2) + std::cout << "operandA is not built and it is an operator, add " + "it to build it later..." + << std::endl; // debug + shape = addEmptyBooleanShapeForCompletion(shapeID, shapes_info_sub); + } + } + // inspectListShapesToBuild(m_shapes_info_sub); // debug + return shape; +} + +GeoShape* ReadGeoModel::addEmptyBooleanShapeForCompletion( + const unsigned int shapeID, type_shapes_boolean_info* shapes_info_sub) { + // get the operands' IDs, + // build an empty instance of the appropriate boolean/operator shape, + // and store all of that together, by appending to this same container, + // so it will be visited at a later time during this very same loop + std::pair<unsigned int, unsigned int> ops = + getBooleanShapeOperands(shapeID); + unsigned int opA = ops.first; + unsigned int opB = ops.second; + + // get the type and create an appropriate empty shape + std::string shType = getShapeType(shapeID); + GeoShape* shape = nullptr; + if (shType == "Intersection") { + shape = new GeoShapeIntersection(); + } else if (shType == "Shift") { + shape = new GeoShapeShift(); + } else if (shType == "Subtraction") { + shape = new GeoShapeSubtraction(); + } else if (shType == "Union") { + shape = new GeoShapeUnion(); + } + tuple_shapes_boolean_info tt(shapeID, shape, opA, opB); + shapes_info_sub->push_back( + tt); //! Push the information about the new boolean shape at the + //! end of the very same container we are iterating over -GeoShape* ReadGeoModel::addEmptyBooleanShapeForCompletion(const unsigned int shapeID, type_shapes_boolean_info* shapes_info_sub) -{ - // get the operands' IDs, - // build an empty instance of the appropriate boolean/operator shape, - // and store all of that together, by appending to this same container, - // so it will be visited at a later time during this very same loop - std::pair<unsigned int, unsigned int> ops = getBooleanShapeOperands(shapeID); - unsigned int opA = ops.first; - unsigned int opB = ops.second; - - // get the type and create an appropriate empty shape - std::string shType = getShapeType(shapeID); - GeoShape* shape = nullptr; - if (shType == "Intersection"){ - shape = new GeoShapeIntersection(); - } else if (shType == "Shift") { - shape = new GeoShapeShift(); - } else if (shType == "Subtraction") { - shape = new GeoShapeSubtraction(); - } else if (shType == "Union") { - shape = new GeoShapeUnion(); - } - - tuple_shapes_boolean_info tt (shapeID, shape, opA, opB); - shapes_info_sub->push_back(tt); //! Push the information about the new boolean shape at the end of the very same container we are iterating over - - return shape; + return shape; } - // TODO: move this to utility class/file -std::vector<std::string> ReadGeoModel::splitString(const std::string& s, const char delimiter) -{ - std::vector<std::string> tokens; - std::string token; - std::istringstream tokenStream(s); - while (std::getline(tokenStream, token, delimiter)) - { - tokens.push_back(token); - } - return tokens; +std::vector<std::string> ReadGeoModel::splitString(const std::string& s, + const char delimiter) { + std::vector<std::string> tokens; + std::string token; + std::istringstream tokenStream(s); + while (std::getline(tokenStream, token, delimiter)) { + tokens.push_back(token); + } + return tokens; } // // TODO: move this to utility class/file -//QStringList ReadGeoModel::toQStringList(std::vector<std::string> vec) +// QStringList ReadGeoModel::toQStringList(std::vector<std::string> vec) // { // QStringList ll; // for ( auto& str : vec ) { @@ -2461,592 +2878,618 @@ std::vector<std::string> ReadGeoModel::splitString(const std::string& s, const c // } //// TODO: move this to utility class/file -//std::vector<std::string> ReadGeoModel::toStdVectorStrings(QStringList qlist) +// std::vector<std::string> ReadGeoModel::toStdVectorStrings(QStringList qlist) //{ -// std::vector<std::string> vec; -// foreach(QString qstr, qlist) { -// vec.push_back(qstr.toStdString()); -// } -// return vec; -//} - - +// std::vector<std::string> vec; +// foreach(QString qstr, qlist) { +// vec.push_back(qstr.toStdString()); +// } +// return vec; +// } // TODO: move this to utility class/file -void ReadGeoModel::printStdVectorStrings(std::vector<std::string> vec) -{ - for ( const auto& str : vec) { - std::cout << str << " "; - } - std::cout << std::endl; - return; +void ReadGeoModel::printStdVectorStrings(std::vector<std::string> vec) { + for (const auto& str : vec) { + std::cout << str << " "; + } + std::cout << std::endl; + return; } +std::pair<unsigned int, unsigned int> ReadGeoModel::getBooleanShapeOperands( + const unsigned int shapeID) { + std::pair<unsigned int, unsigned int> pair; -std::pair<unsigned int, unsigned int> ReadGeoModel::getBooleanShapeOperands(const unsigned int shapeID) -{ - std::pair<unsigned int, unsigned int> pair; - -// std::vector<std::string> paramsShape = toStdVectorStrings(m_shapes[ shapeID ]); - std::vector<std::string> paramsShape = m_shapes[ shapeID-1 ];// remember: shapes' IDs start from 1 - -// unsigned int id = std::stoi(paramsShape[0]); //! the ID of the boolean/operator shape - std::string type = paramsShape[1]; //! the GeoModel type of the shape - std::string parameters = paramsShape[2]; //! the parameters defining the shape, coming from the DB - - //! The Subtraction boolean shape has two operands, here we store their IDs - unsigned int opA = 0; - unsigned int opB = 0; - // get parameters from DB string - std::vector<std::string> shapePars = splitString( parameters, ';' ); - // std::cout << "shapePars size: " << shapePars.size() << std::endl; // debug only - - for (auto par : shapePars) { - std::vector<std::string> vars = splitString(par, '='); - std::string varName = vars[0]; - std::string varValue = vars[1]; - // std::cout << "vars ==> " << vars[0] << ", " << vars[1] << std::endl; // debug - if ( isShapeBoolean(type) ) { - if (varName == "opA") opA = std::stoi(varValue); - if (varName == "opB") opB = std::stoi(varValue); - } else if ("Shift" == type) { - if (varName == "A") opA = std::stoi(varValue); - if (varName == "X") opB = std::stoi(varValue); - } else { - std::cout << "ERROR!!! This type of shape cannot be handled here: " << type << ", --> Exiting..." << std::endl; - exit(EXIT_FAILURE); + // std::vector<std::string> paramsShape = toStdVectorStrings(m_shapes[ + // shapeID ]); + std::vector<std::string> paramsShape = + m_shapes[shapeID - 1]; // remember: shapes' IDs start from 1 + + // unsigned int id = std::stoi(paramsShape[0]); //! the ID of the + // boolean/operator shape + std::string type = paramsShape[1]; //! the GeoModel type of the shape + std::string parameters = paramsShape[2]; //! the parameters defining the + //! shape, coming from the DB + + //! The Subtraction boolean shape has two operands, here we store their IDs + unsigned int opA = 0; + unsigned int opB = 0; + // get parameters from DB string + std::vector<std::string> shapePars = splitString(parameters, ';'); + // std::cout << "shapePars size: " << shapePars.size() << std::endl; // + // debug only + + for (auto par : shapePars) { + std::vector<std::string> vars = splitString(par, '='); + std::string varName = vars[0]; + std::string varValue = vars[1]; + // std::cout << "vars ==> " << vars[0] << ", " << vars[1] << std::endl; + // // debug + if (isShapeBoolean(type)) { + if (varName == "opA") opA = std::stoi(varValue); + if (varName == "opB") opB = std::stoi(varValue); + } else if ("Shift" == type) { + if (varName == "A") opA = std::stoi(varValue); + if (varName == "X") opB = std::stoi(varValue); + } else { + std::cout << "ERROR!!! This type of shape cannot be handled here: " + << type << ", --> Exiting..." << std::endl; + exit(EXIT_FAILURE); + } } - } - if (opA == 0 || opB == 0) { - std::cout << "ERROR! Intersection/Subtraction/Union/Shift shape - operands' IDs are empty! (opA: " << opA << ", opB:" << opB << ")" << std::endl; - exit(EXIT_FAILURE); - } - pair.first = opA; - pair.second = opB; + if (opA == 0 || opB == 0) { + std::cout << "ERROR! Intersection/Subtraction/Union/Shift shape - " + "operands' IDs are empty! (opA: " + << opA << ", opB:" << opB << ")" << std::endl; + exit(EXIT_FAILURE); + } + pair.first = opA; + pair.second = opB; - return pair; + return pair; } - -bool ReadGeoModel::isShapeOperator(const unsigned int shapeId) -{ - return isShapeOperator( getShapeType(shapeId) ); +bool ReadGeoModel::isShapeOperator(const unsigned int shapeId) { + return isShapeOperator(getShapeType(shapeId)); } -bool ReadGeoModel::isShapeOperator(const std::string type) -{ - std::unordered_set<std::string> opShapes = {"Intersection", "Shift", "Subtraction", "Union"}; - return (opShapes.find(type) != opShapes.end()); +bool ReadGeoModel::isShapeOperator(const std::string type) { + std::unordered_set<std::string> opShapes = {"Intersection", "Shift", + "Subtraction", "Union"}; + return (opShapes.find(type) != opShapes.end()); } -bool ReadGeoModel::isShapeBoolean(const unsigned int shapeId) -{ - return isShapeBoolean( getShapeType(shapeId) ); +bool ReadGeoModel::isShapeBoolean(const unsigned int shapeId) { + return isShapeBoolean(getShapeType(shapeId)); } -bool ReadGeoModel::isShapeBoolean(const std::string type) -{ - std::unordered_set<std::string> opShapes = {"Intersection", "Subtraction", "Union"}; - return (opShapes.find(type) != opShapes.end()); +bool ReadGeoModel::isShapeBoolean(const std::string type) { + std::unordered_set<std::string> opShapes = {"Intersection", "Subtraction", + "Union"}; + return (opShapes.find(type) != opShapes.end()); } - - - GeoBox* ReadGeoModel::buildDummyShape() { - return new GeoBox(30.0*SYSTEM_OF_UNITS::cm, 30*SYSTEM_OF_UNITS::cm, 30*SYSTEM_OF_UNITS::cm); + return new GeoBox(30.0 * SYSTEM_OF_UNITS::cm, 30 * SYSTEM_OF_UNITS::cm, + 30 * SYSTEM_OF_UNITS::cm); } +GeoLogVol* ReadGeoModel::buildLogVol(const unsigned int id) { + if (m_loglevel >= 2) { + muxCout.lock(); + std::cout << "buildLogVol(), testing LogVol id: " << id << "...\n"; + ; + muxCout.unlock(); + } -GeoLogVol* ReadGeoModel::buildLogVol(const unsigned int id) -{ + if (isBuiltLog(id)) { + if (m_loglevel >= 2) { + muxCout.lock(); + std::cout << "getting the LogVol from cache...\n"; + ; + muxCout.unlock(); + } + return getBuiltLog(id); + } - if (m_deepDebug) { muxCout.lock(); std::cout << "buildLogVol(), testing LogVol id: " << id << "...\n"; ; muxCout.unlock(); } + if (m_loglevel >= 2) { + muxCout.lock(); + std::cout << "ReadGeoModel::buildLogVol()" << std::endl; + muxCout.unlock(); + } - if (isBuiltLog(id)) { - if (m_deepDebug) { muxCout.lock(); std::cout << "getting the LogVol from cache...\n"; ; muxCout.unlock(); } - return getBuiltLog(id); - } + // get logVol properties from the DB + std::vector<std::string> values = m_logVols[id - 1]; - if (m_deepDebug) { - muxCout.lock(); - std::cout << "ReadGeoModel::buildLogVol()" << std::endl; - muxCout.unlock(); - } + // get the parameters to build the GeoLogVol node + std::string logVolName = values[1]; - // get logVol properties from the DB - std::vector<std::string> values = m_logVols[id-1]; + // build the referenced GeoShape node + const unsigned int shapeId = std::stoi(values[2]); + GeoShape* shape = getBuiltShape(shapeId); + if (!shape) { + std::cout + << "ERROR!! While building a LogVol, Shape is NULL! Exiting..." + << std::endl; + exit(EXIT_FAILURE); + } - // get the parameters to build the GeoLogVol node - std::string logVolName = values[1]; + // build the referenced GeoMaterial node + const unsigned int matId = std::stoi(values[3]); + if (m_loglevel >= 2) { + muxCout.lock(); + std::cout << "buildLogVol() - material Id:" << matId << std::endl; + muxCout.unlock(); + } + GeoMaterial* mat = getBuiltMaterial(matId); + if (!mat) { + std::cout + << "ERROR!! While building a LogVol, Material is NULL! Exiting..." + << std::endl; + exit(EXIT_FAILURE); + } - // build the referenced GeoShape node - const unsigned int shapeId = std::stoi(values[2]); - GeoShape* shape = getBuiltShape(shapeId); - if(!shape) { - std::cout << "ERROR!! While building a LogVol, Shape is NULL! Exiting..." <<std::endl; - exit(EXIT_FAILURE); - } + GeoLogVol* logPtr = new GeoLogVol(logVolName, shape, mat); + storeBuiltLog(logPtr); + if (m_loglevel >= 2) { + muxCout.lock(); + std::cout << "buildLogVol() - address of the stored LogVol:" << logPtr + << std::endl; + muxCout.unlock(); + } + return logPtr; +} - // build the referenced GeoMaterial node - const unsigned int matId = std::stoi(values[3]); - if (m_deepDebug) { - muxCout.lock(); - std::cout << "buildLogVol() - material Id:" << matId << std::endl; - muxCout.unlock(); - } - GeoMaterial* mat = getBuiltMaterial(matId); - if(!mat) { - std::cout << "ERROR!! While building a LogVol, Material is NULL! Exiting..." <<std::endl; - exit(EXIT_FAILURE); - } - - GeoLogVol* logPtr = new GeoLogVol(logVolName, shape, mat); - storeBuiltLog(logPtr); - if (m_deepDebug) { - muxCout.lock(); - std::cout << "buildLogVol() - address of the stored LogVol:" << logPtr << std::endl; - muxCout.unlock(); - } - return logPtr; -} - - -//// TODO: should go in a QtUtils header-only class, to be used in other packages -//QList<double> ReadGeoModel::convertQstringListToDouble(QStringList listin) { -// QList<double> listout; -// foreach (const QString &s, listin) { -// listout.append(s.toDouble()); -// } -// return listout; -//} +//// TODO: should go in a QtUtils header-only class, to be used in other +/// packages +// QList<double> ReadGeoModel::convertQstringListToDouble(QStringList listin) { +// QList<double> listout; +// foreach (const QString &s, listin) { +// listout.append(s.toDouble()); +// } +// return listout; +// } //// TODO: move it to an utility class -//void ReadGeoModel::printTransformationValues(QStringList values) { -// QList<double> t = convertQstringListToDouble(values); -// muxCout.lock(); -// std::cout << "transformation input values: " << std::endl; -// std::cout << "[[" << t[0] << "," << t[1] << "," << t[2] << "][" -// << t[3] << "," << t[4] << "," << t[5] << "][" -// << t[6] << "," << t[7] << "," << t[8] << "][" -// << t[9] << "," << t[10] << "," << t[11] << "]]" << std::endl; -// muxCout.unlock(); -//} - +// void ReadGeoModel::printTransformationValues(QStringList values) { +// QList<double> t = convertQstringListToDouble(values); +// muxCout.lock(); +// std::cout << "transformation input values: " << std::endl; +// std::cout << "[[" << t[0] << "," << t[1] << "," << t[2] << "][" +// << t[3] << "," << t[4] << "," << t[5] << "][" +// << t[6] << "," << t[7] << "," << t[8] << "][" +// << t[9] << "," << t[10] << "," << t[11] << "]]" << +// std::endl; +// muxCout.unlock(); +// } -GeoAlignableTransform* ReadGeoModel::buildAlignableTransform(const unsigned int id) -{ - if (isBuiltAlignableTransform(id)) { - return getBuiltAlignableTransform(id); - } +GeoAlignableTransform* ReadGeoModel::buildAlignableTransform( + const unsigned int id) { + if (isBuiltAlignableTransform(id)) { + return getBuiltAlignableTransform(id); + } - std::vector<std::string> values = m_alignableTransforms[id-1]; // nodes' IDs start from 1 - values.erase(values.begin()); // remove the first element, that is the 'id', leaving the other items in the list + std::vector<std::string> values = + m_alignableTransforms[id - 1]; // nodes' IDs start from 1 + values.erase(values.begin()); // remove the first element, that is the + // 'id', leaving the other items in the list - // get the 12 matrix elements - double xx = std::stod(values[0]); - double xy = std::stod(values[1]); - double xz = std::stod(values[2]); + // get the 12 matrix elements + double xx = std::stod(values[0]); + double xy = std::stod(values[1]); + double xz = std::stod(values[2]); - double yx = std::stod(values[3]); - double yy = std::stod(values[4]); - double yz = std::stod(values[5]); + double yx = std::stod(values[3]); + double yy = std::stod(values[4]); + double yz = std::stod(values[5]); - double zx = std::stod(values[6]); - double zy = std::stod(values[7]); - double zz = std::stod(values[8]); + double zx = std::stod(values[6]); + double zy = std::stod(values[7]); + double zz = std::stod(values[8]); - double dx = std::stod(values[9]); - double dy = std::stod(values[10]); - double dz = std::stod(values[11]); + double dx = std::stod(values[9]); + double dy = std::stod(values[10]); + double dz = std::stod(values[11]); - GeoTrf::Transform3D txf; - // build the rotation matrix with the first 9 elements - txf(0,0)=xx; - txf(0,1)=xy; - txf(0,2)=xz; + GeoTrf::Transform3D txf; + // build the rotation matrix with the first 9 elements + txf(0, 0) = xx; + txf(0, 1) = xy; + txf(0, 2) = xz; - txf(1,0)=yx; - txf(1,1)=yy; - txf(1,2)=yz; + txf(1, 0) = yx; + txf(1, 1) = yy; + txf(1, 2) = yz; - txf(2,0)=zx; - txf(2,1)=zy; - txf(2,2)=zz; + txf(2, 0) = zx; + txf(2, 1) = zy; + txf(2, 2) = zz; - // build the translation matrix with the last 3 elements - txf(0,3)=dx; - txf(1,3)=dy; - txf(2,3)=dz; + // build the translation matrix with the last 3 elements + txf(0, 3) = dx; + txf(1, 3) = dy; + txf(2, 3) = dz; - // GeoUtilFunctions::printTrf(txf); // DEBUG - GeoAlignableTransform* tr = new GeoAlignableTransform(txf); - storeBuiltAlignableTransform(tr); - return tr; + // GeoUtilFunctions::printTrf(txf); // DEBUG + GeoAlignableTransform* tr = new GeoAlignableTransform(txf); + storeBuiltAlignableTransform(tr); + return tr; } +GeoTransform* ReadGeoModel::buildTransform(const unsigned int id) { + if (isBuiltTransform(id)) { + return getBuiltTransform(id); + } -GeoTransform* ReadGeoModel::buildTransform(const unsigned int id) -{ - if (isBuiltTransform(id)) { - return getBuiltTransform(id); - } - - std::vector<std::string> values = m_transforms[id-1]; // nodes' IDs start from 1 - values.erase(values.begin()); // remove the first element, that is the 'id', leaving the other items in the list + std::vector<std::string> values = + m_transforms[id - 1]; // nodes' IDs start from 1 + values.erase(values.begin()); // remove the first element, that is the + // 'id', leaving the other items in the list - // get the 12 matrix elements - double xx = std::stod(values[0]); - double xy = std::stod(values[1]); - double xz = std::stod(values[2]); + // get the 12 matrix elements + double xx = std::stod(values[0]); + double xy = std::stod(values[1]); + double xz = std::stod(values[2]); - double yx = std::stod(values[3]); - double yy = std::stod(values[4]); - double yz = std::stod(values[5]); + double yx = std::stod(values[3]); + double yy = std::stod(values[4]); + double yz = std::stod(values[5]); - double zx = std::stod(values[6]); - double zy = std::stod(values[7]); - double zz = std::stod(values[8]); + double zx = std::stod(values[6]); + double zy = std::stod(values[7]); + double zz = std::stod(values[8]); - double dx = std::stod(values[9]); - double dy = std::stod(values[10]); - double dz = std::stod(values[11]); + double dx = std::stod(values[9]); + double dy = std::stod(values[10]); + double dz = std::stod(values[11]); - GeoTrf::Transform3D txf; - // build the rotation matrix with the first 9 elements - txf(0,0)=xx; - txf(0,1)=xy; - txf(0,2)=xz; + GeoTrf::Transform3D txf; + // build the rotation matrix with the first 9 elements + txf(0, 0) = xx; + txf(0, 1) = xy; + txf(0, 2) = xz; - txf(1,0)=yx; - txf(1,1)=yy; - txf(1,2)=yz; + txf(1, 0) = yx; + txf(1, 1) = yy; + txf(1, 2) = yz; - txf(2,0)=zx; - txf(2,1)=zy; - txf(2,2)=zz; + txf(2, 0) = zx; + txf(2, 1) = zy; + txf(2, 2) = zz; - // build the translation matrix with the last 3 elements - txf(0,3) = dx; - txf(1,3) = dy; - txf(2,3) = dz; + // build the translation matrix with the last 3 elements + txf(0, 3) = dx; + txf(1, 3) = dy; + txf(2, 3) = dz; - // GeoUtilsFunctions::printTrf(txf); // DEBUG - GeoTransform* tr = new GeoTransform(txf); - storeBuiltTransform(tr); - return tr; + // GeoUtilsFunctions::printTrf(txf); // DEBUG + GeoTransform* tr = new GeoTransform(txf); + storeBuiltTransform(tr); + return tr; } +GeoSerialTransformer* ReadGeoModel::buildSerialTransformer( + const unsigned int id) { + muxCout.lock(); + if (m_loglevel >= 2) + std::cout << "ReadGeoModel::buildSerialTransformer()" << std::endl; + muxCout.unlock(); -GeoSerialTransformer* ReadGeoModel::buildSerialTransformer(const unsigned int id) -{ - muxCout.lock(); - if (m_deepDebug) std::cout << "ReadGeoModel::buildSerialTransformer()" << std::endl; - muxCout.unlock(); - - const unsigned int nodeID = id-1; // nodes' IDs start from 1 - std::vector<std::string> values = m_serialTransformers[nodeID]; - - const unsigned int functionId = std::stoi(values[1]); - const unsigned int physVolId = std::stoi(values[2]); - const unsigned int physVolTableId = std::stoi(values[3]); - const unsigned int copies = std::stoi(values[4]); - - // GET THE REFERENCED FUNCTION - TRANSFUNCTION func = buildFunction(functionId); - - // GET THE REFERENCED VPHYSVOL - const GeoVPhysVol* vphysVol = buildVPhysVolInstance(physVolId, physVolTableId, 1); // we use "1" as default copyNumber: taking the first copy of the VPhysVol as the referenced volume - - // get PhysVol or FullPhysVol pointer and return the SerialTransformer - if (dynamic_cast<const GeoFullPhysVol*>(vphysVol)) { - const GeoFullPhysVol* vol = dynamic_cast<const GeoFullPhysVol*>(vphysVol); - GeoSerialTransformer* nodePtr = new GeoSerialTransformer(vol, &func, copies ); + const unsigned int nodeID = id - 1; // nodes' IDs start from 1 + std::vector<std::string> values = m_serialTransformers[nodeID]; + + const unsigned int functionId = std::stoi(values[1]); + const unsigned int physVolId = std::stoi(values[2]); + const unsigned int physVolTableId = std::stoi(values[3]); + const unsigned int copies = std::stoi(values[4]); + + // GET THE REFERENCED FUNCTION + TRANSFUNCTION func = buildFunction(functionId); + + // GET THE REFERENCED VPHYSVOL + const GeoVPhysVol* vphysVol = buildVPhysVolInstance( + physVolId, physVolTableId, + 1); // we use "1" as default copyNumber: taking the first copy of the + // VPhysVol as the referenced volume + + // get PhysVol or FullPhysVol pointer and return the SerialTransformer + if (dynamic_cast<const GeoFullPhysVol*>(vphysVol)) { + const GeoFullPhysVol* vol = + dynamic_cast<const GeoFullPhysVol*>(vphysVol); + GeoSerialTransformer* nodePtr = + new GeoSerialTransformer(vol, &func, copies); + storeBuiltSerialTransformer(nodePtr); + return nodePtr; + } + const GeoPhysVol* vol = dynamic_cast<const GeoPhysVol*>(vphysVol); + GeoSerialTransformer* nodePtr = + new GeoSerialTransformer(vol, &func, copies); storeBuiltSerialTransformer(nodePtr); return nodePtr; - } - const GeoPhysVol* vol = dynamic_cast<const GeoPhysVol*>(vphysVol); - GeoSerialTransformer* nodePtr = new GeoSerialTransformer(vol, &func, copies ); - storeBuiltSerialTransformer(nodePtr); - return nodePtr; } -TRANSFUNCTION ReadGeoModel::buildFunction(const unsigned int id) -{ - /* FIXME: see below - if( isBuiltFunction(id) ) { - GeoXF::Function* fPtr = getBuiltFunction(id); - TRANSFUNCTION tf = (*fPtr); // Remember: "typedef const Function & TRANSFUNCTION" - return tf; - } - */ - - std::string expr = m_functions[id-1][1]; // nodes' IDs start from 1 - - if (0==expr.size()) { - muxCout.lock(); - std::cout << "FATAL ERROR!! Function expression is empty!! Aborting..." << std::endl; - muxCout.unlock(); - exit(EXIT_FAILURE); - } +TRANSFUNCTION ReadGeoModel::buildFunction(const unsigned int id) { + /* FIXME: see below + if( isBuiltFunction(id) ) { + GeoXF::Function* fPtr = getBuiltFunction(id); + TRANSFUNCTION tf = (*fPtr); // Remember: "typedef const Function & + TRANSFUNCTION" return tf; + } + */ - TransFunctionInterpreter interpreter; - TFPTR func=interpreter.interpret( expr ); - TRANSFUNCTION tf = *(func.release()); // make func returns a pointer to the managed object and releases the ownership, then get the object dereferencing the pointer + std::string expr = m_functions[id - 1][1]; // nodes' IDs start from 1 - /* FIXME: At the moment, enabling this cache makes the app crash at the end, when calling the destructor. I suspect because the pointers are not correct and so removing them throws an error. - // Get a non-const pointer to the Function object, - // and store that into the cache. - // Remember: "typedef const Function & TRANSFUNCTION" - const GeoXF::Function* fPtrConst = &tf; - GeoXF::Function* fPtr = const_cast <GeoXF::Function*>(fPtrConst); - storeBuiltFunction(id, fPtr); - */ + if (0 == expr.size()) { + muxCout.lock(); + std::cout << "FATAL ERROR!! Function expression is empty!! Aborting..." + << std::endl; + muxCout.unlock(); + exit(EXIT_FAILURE); + } - return tf; + TransFunctionInterpreter interpreter; + TFPTR func = interpreter.interpret(expr); + TRANSFUNCTION tf = + *(func.release()); // make func returns a pointer to the managed + // object and releases the ownership, then get + // the object dereferencing the pointer + + //-- FIXME: At the moment, enabling this cache makes the app crash at the + //-- end, when calling the destructor. I suspect because the pointers are + //-- not correct and so removing them throws an error. + // Get a non-const pointer to the Function object, + // and store that into the cache. + // Remember: "typedef const Function & TRANSFUNCTION" + /* + const GeoXF::Function* fPtrConst = &tf; + GeoXF::Function* fPtr = const_cast<GeoXF::Function*>(fPtrConst); + storeBuiltFunction(id, fPtr); + */ + + return tf; } - - // --- methods for caching GeoShape nodes --- -bool ReadGeoModel::isBuiltShape(const unsigned int id) -{ - return ( ! (m_memMapShapes.find(id) == m_memMapShapes.end()) ); +bool ReadGeoModel::isBuiltShape(const unsigned int id) { + return (!(m_memMapShapes.find(id) == m_memMapShapes.end())); } -void ReadGeoModel::storeBuiltShape(const unsigned int id, GeoShape* nodePtr) -{ - m_memMapShapes[id] = nodePtr; +void ReadGeoModel::storeBuiltShape(const unsigned int id, GeoShape* nodePtr) { + m_memMapShapes[id] = nodePtr; } -GeoShape* ReadGeoModel::getBuiltShape(const unsigned int id) -{ - return m_memMapShapes[id]; // this is a map, and 'id' is the key +GeoShape* ReadGeoModel::getBuiltShape(const unsigned int id) { + return m_memMapShapes[id]; // this is a map, and 'id' is the key } // --- methods for caching GeoLogVol nodes --- -bool ReadGeoModel::isBuiltLog(const unsigned int id) -{ - return (id <= m_memMapLogVols.size()); // vector: we exploit the fact that we built the vols ordered by their IDs +bool ReadGeoModel::isBuiltLog(const unsigned int id) { + return (id <= + m_memMapLogVols.size()); // vector: we exploit the fact that we + // built the vols ordered by their IDs } -void ReadGeoModel::storeBuiltLog(GeoLogVol* nodePtr) -{ - m_memMapLogVols.push_back(nodePtr);// vector: we exploit the fact that we built the vols ordered by their IDs +void ReadGeoModel::storeBuiltLog(GeoLogVol* nodePtr) { + m_memMapLogVols.push_back(nodePtr); // vector: we exploit the fact that we + // built the vols ordered by their IDs } -GeoLogVol* ReadGeoModel::getBuiltLog(const unsigned int id) -{ - return m_memMapLogVols[id-1]; // nodes' IDs start from 1 +GeoLogVol* ReadGeoModel::getBuiltLog(const unsigned int id) { + return m_memMapLogVols[id - 1]; // nodes' IDs start from 1 } // --- methods for caching GeoPhysVol nodes --- -bool ReadGeoModel::isBuiltPhysVol(const unsigned int id) -{ - return (id <= m_memMapPhysVols.size()); // vector: we exploit the fact that we built the vols ordered by their IDs +bool ReadGeoModel::isBuiltPhysVol(const unsigned int id) { + return (id <= + m_memMapPhysVols.size()); // vector: we exploit the fact that we + // built the vols ordered by their IDs } -void ReadGeoModel::storeBuiltPhysVol(GeoPhysVol* nodePtr) -{ - m_memMapPhysVols.push_back(nodePtr); // vector: we exploit the fact that we built the vols ordered by their IDs +void ReadGeoModel::storeBuiltPhysVol(GeoPhysVol* nodePtr) { + m_memMapPhysVols.push_back(nodePtr); // vector: we exploit the fact that we + // built the vols ordered by their IDs } -GeoPhysVol* ReadGeoModel::getBuiltPhysVol(const unsigned int id) -{ - return m_memMapPhysVols[id-1]; // nodes' IDs start from 1 +GeoPhysVol* ReadGeoModel::getBuiltPhysVol(const unsigned int id) { + return m_memMapPhysVols[id - 1]; // nodes' IDs start from 1 } // --- methods for caching GeoFullPhysVol nodes --- -bool ReadGeoModel::isBuiltFullPhysVol(const unsigned int id) -{ - return (id <= m_memMapFullPhysVols.size()); // vector: we exploit the fact that we built the vols ordered by their IDs - +bool ReadGeoModel::isBuiltFullPhysVol(const unsigned int id) { + return ( + id <= + m_memMapFullPhysVols.size()); // vector: we exploit the fact that we + // built the vols ordered by their IDs } -void ReadGeoModel::storeBuiltFullPhysVol(GeoFullPhysVol* nodePtr) -{ - m_memMapFullPhysVols.push_back(nodePtr); // vector, we store them in the order of IDs +void ReadGeoModel::storeBuiltFullPhysVol(GeoFullPhysVol* nodePtr) { + m_memMapFullPhysVols.push_back( + nodePtr); // vector, we store them in the order of IDs } -GeoFullPhysVol* ReadGeoModel::getBuiltFullPhysVol(const unsigned int id) -{ - return m_memMapFullPhysVols[id-1]; // nodes' IDs start from 1 - +GeoFullPhysVol* ReadGeoModel::getBuiltFullPhysVol(const unsigned int id) { + return m_memMapFullPhysVols[id - 1]; // nodes' IDs start from 1 } // --- methods for caching GeoMaterial nodes --- -bool ReadGeoModel::isBuiltMaterial(const unsigned int id) -{ - return (id <= m_memMapMaterials.size()); +bool ReadGeoModel::isBuiltMaterial(const unsigned int id) { + return (id <= m_memMapMaterials.size()); } -void ReadGeoModel::storeBuiltMaterial(GeoMaterial* nodePtr) -{ - m_memMapMaterials.push_back(nodePtr); // we store them in the order of IDs +void ReadGeoModel::storeBuiltMaterial(GeoMaterial* nodePtr) { + m_memMapMaterials.push_back(nodePtr); // we store them in the order of IDs } -GeoMaterial* ReadGeoModel::getBuiltMaterial(const unsigned int id) -{ - return m_memMapMaterials[id-1]; +GeoMaterial* ReadGeoModel::getBuiltMaterial(const unsigned int id) { + return m_memMapMaterials[id - 1]; } // --- methods for caching GeoElement nodes --- -bool ReadGeoModel::isBuiltElement(const unsigned int id) -{ - return (id <= m_memMapElements.size()); +bool ReadGeoModel::isBuiltElement(const unsigned int id) { + return (id <= m_memMapElements.size()); } -void ReadGeoModel::storeBuiltElement(GeoElement* nodePtr) -{ - m_memMapElements.push_back(nodePtr); // vector, we store them in the order of IDs +void ReadGeoModel::storeBuiltElement(GeoElement* nodePtr) { + m_memMapElements.push_back( + nodePtr); // vector, we store them in the order of IDs } -GeoElement* ReadGeoModel::getBuiltElement(const unsigned int id) -{ - return m_memMapElements[id-1]; +GeoElement* ReadGeoModel::getBuiltElement(const unsigned int id) { + return m_memMapElements[id - 1]; } // --- methods for caching GeoTransform nodes --- -bool ReadGeoModel::isBuiltTransform(const unsigned int id) -{ - return (id <= m_memMapTransforms.size()); // vector: we exploit the fact that we built the vols ordered by their IDs +bool ReadGeoModel::isBuiltTransform(const unsigned int id) { + return (id <= + m_memMapTransforms.size()); // vector: we exploit the fact that we + // built the vols ordered by their IDs } -void ReadGeoModel::storeBuiltTransform(GeoTransform* nodePtr) -{ - m_memMapTransforms.push_back(nodePtr); // vector, we store them in the order of IDs - +void ReadGeoModel::storeBuiltTransform(GeoTransform* nodePtr) { + m_memMapTransforms.push_back( + nodePtr); // vector, we store them in the order of IDs } -GeoTransform* ReadGeoModel::getBuiltTransform(const unsigned int id) -{ - return m_memMapTransforms[id-1]; // nodes' IDs start from 1 +GeoTransform* ReadGeoModel::getBuiltTransform(const unsigned int id) { + return m_memMapTransforms[id - 1]; // nodes' IDs start from 1 } // --- methods for caching GeoAlignableTransform nodes --- -bool ReadGeoModel::isBuiltAlignableTransform(const unsigned int id) -{ - return (id <= m_memMapAlignableTransforms.size()); // vector: we exploit the fact that we built the vols ordered by their IDs +bool ReadGeoModel::isBuiltAlignableTransform(const unsigned int id) { + return (id <= m_memMapAlignableTransforms + .size()); // vector: we exploit the fact that we built + // the vols ordered by their IDs } -void ReadGeoModel::storeBuiltAlignableTransform(GeoAlignableTransform* nodePtr) -{ - m_memMapAlignableTransforms.push_back(nodePtr); // vector, we store them in the order of IDs - +void ReadGeoModel::storeBuiltAlignableTransform( + GeoAlignableTransform* nodePtr) { + m_memMapAlignableTransforms.push_back( + nodePtr); // vector, we store them in the order of IDs } -GeoAlignableTransform* ReadGeoModel::getBuiltAlignableTransform(const unsigned int id) -{ - return m_memMapAlignableTransforms[id-1]; // nodes' IDs start from 1 - +GeoAlignableTransform* ReadGeoModel::getBuiltAlignableTransform( + const unsigned int id) { + return m_memMapAlignableTransforms[id - 1]; // nodes' IDs start from 1 } // --- methods for caching GeoSerialDenominator nodes --- -bool ReadGeoModel::isBuiltSerialDenominator(const unsigned int id) // TODO: not used at the moment, implemnt the use of this method!! and check all the others too...!! +bool ReadGeoModel::isBuiltSerialDenominator( + const unsigned int id) // TODO: not used at the moment, implemnt the use of + // this method!! and check all the others too...!! { - return (id <= m_memMapSerialDenominators.size()); // vector: we exploit the fact that we built the vols ordered by their IDs + return (id <= m_memMapSerialDenominators + .size()); // vector: we exploit the fact that we built + // the vols ordered by their IDs } -void ReadGeoModel::storeBuiltSerialDenominator(GeoSerialDenominator* nodePtr) -{ - m_memMapSerialDenominators.push_back(nodePtr); // vector, we store them in the order of IDs +void ReadGeoModel::storeBuiltSerialDenominator(GeoSerialDenominator* nodePtr) { + m_memMapSerialDenominators.push_back( + nodePtr); // vector, we store them in the order of IDs } -GeoSerialDenominator* ReadGeoModel::getBuiltSerialDenominator(const unsigned int id) -{ - return m_memMapSerialDenominators[id-1]; // nodes' IDs start from 1 - +GeoSerialDenominator* ReadGeoModel::getBuiltSerialDenominator( + const unsigned int id) { + return m_memMapSerialDenominators[id - 1]; // nodes' IDs start from 1 } // --- methods for caching GeoSerialIdentifier nodes --- -bool ReadGeoModel::isBuiltSerialIdentifier(const unsigned int id) -{ - return (id <= m_memMapSerialIdentifiers.size()); // vector: we exploit the fact that we built the vols ordered by their IDs +bool ReadGeoModel::isBuiltSerialIdentifier(const unsigned int id) { + return (id <= m_memMapSerialIdentifiers + .size()); // vector: we exploit the fact that we built + // the vols ordered by their IDs } -void ReadGeoModel::storeBuiltSerialIdentifier(GeoSerialIdentifier* nodePtr) -{ - m_memMapSerialIdentifiers.push_back(nodePtr); // vector, we store them in the order of IDs +void ReadGeoModel::storeBuiltSerialIdentifier(GeoSerialIdentifier* nodePtr) { + m_memMapSerialIdentifiers.push_back( + nodePtr); // vector, we store them in the order of IDs } -GeoSerialIdentifier* ReadGeoModel::getBuiltSerialIdentifier(const unsigned int id) -{ - return m_memMapSerialIdentifiers[id-1]; // nodes' IDs start from 1 - +GeoSerialIdentifier* ReadGeoModel::getBuiltSerialIdentifier( + const unsigned int id) { + return m_memMapSerialIdentifiers[id - 1]; // nodes' IDs start from 1 } // --- methods for caching GeoIdentifierTag nodes --- -bool ReadGeoModel::isBuiltIdentifierTag(const unsigned int id) -{ - return (id <= m_memMapIdentifierTags.size()); // vector: we exploit the fact that we built the vols ordered by their IDs -} -void ReadGeoModel::storeBuiltIdentifierTag(GeoIdentifierTag* nodePtr) -{ - m_memMapIdentifierTags.push_back(nodePtr); // vector, we store them in the order of IDs -} -GeoIdentifierTag* ReadGeoModel::getBuiltIdentifierTag(const unsigned int id) -{ - if (0 == m_memMapIdentifierTags.size()) - std::cout << "WARNING!!! vector is empty! A crash is on its way..." << std::endl; // TODO: make this check for all get methods, to catch the situation when a new GeoModel class is added but no buildAllXXX method is called. - return m_memMapIdentifierTags[id-1]; // nodes' IDs start from 1 - +bool ReadGeoModel::isBuiltIdentifierTag(const unsigned int id) { + return ( + id <= + m_memMapIdentifierTags.size()); // vector: we exploit the fact that we + // built the vols ordered by their IDs +} +void ReadGeoModel::storeBuiltIdentifierTag(GeoIdentifierTag* nodePtr) { + m_memMapIdentifierTags.push_back( + nodePtr); // vector, we store them in the order of IDs +} +GeoIdentifierTag* ReadGeoModel::getBuiltIdentifierTag(const unsigned int id) { + if (0 == m_memMapIdentifierTags.size()) + std::cout + << "WARNING!!! vector is empty! A crash is on its way..." + << std::endl; // TODO: make this check for all get methods, to + // catch the situation when a new GeoModel class is + // added but no buildAllXXX method is called. + return m_memMapIdentifierTags[id - 1]; // nodes' IDs start from 1 } // --- methods for caching GeoNameTag nodes --- -bool ReadGeoModel::isBuiltNameTag(const unsigned int id) -{ - return (id <= m_memMapNameTags.size()); // vector: we exploit the fact that we built the vols ordered by their IDs +bool ReadGeoModel::isBuiltNameTag(const unsigned int id) { + return (id <= + m_memMapNameTags.size()); // vector: we exploit the fact that we + // built the vols ordered by their IDs } -void ReadGeoModel::storeBuiltNameTag(GeoNameTag* nodePtr) -{ - m_memMapNameTags.push_back(nodePtr); // vector, we store them in the order of IDs - +void ReadGeoModel::storeBuiltNameTag(GeoNameTag* nodePtr) { + m_memMapNameTags.push_back( + nodePtr); // vector, we store them in the order of IDs } -GeoNameTag* ReadGeoModel::getBuiltNameTag(const unsigned int id) -{ - return m_memMapNameTags[id-1]; // vector, but nodes' IDs start from 1 - +GeoNameTag* ReadGeoModel::getBuiltNameTag(const unsigned int id) { + return m_memMapNameTags[id - 1]; // vector, but nodes' IDs start from 1 } // --- methods for caching GeoSerialTransformer nodes --- -bool ReadGeoModel::isBuiltSerialTransformer(const unsigned int id) +bool ReadGeoModel::isBuiltSerialTransformer(const unsigned int id) { + return (id <= m_memMapSerialTransformers + .size()); // vector: we exploit the fact that we built + // the vols ordered by their IDs +} +// void ReadGeoModel::storeBuiltSerialTransformer(const unsigned int id, +// GeoSerialTransformer* nodePtr) +void ReadGeoModel::storeBuiltSerialTransformer(GeoSerialTransformer* nodePtr) { + m_memMapSerialTransformers.push_back( + nodePtr); // vector, we store them in the order of IDs +} +GeoSerialTransformer* ReadGeoModel::getBuiltSerialTransformer( + const unsigned int id) { + return m_memMapSerialTransformers[id - 1]; // remember: nodes' IDs + // start from 1 +} +/* FIXME: +// --- methods for caching Functions nodes --- +bool ReadGeoModel::isBuiltFunction(const unsigned int id) { - return (id <= m_memMapSerialTransformers.size()); // vector: we exploit the fact that we built the vols ordered by their IDs + return (id <= m_memMapFunctions.size()); // vector: we exploit the fact that +we built the vols ordered by their IDs } -//void ReadGeoModel::storeBuiltSerialTransformer(const unsigned int id, GeoSerialTransformer* nodePtr) -void ReadGeoModel::storeBuiltSerialTransformer(GeoSerialTransformer* nodePtr) +void ReadGeoModel::storeBuiltFunction(const unsigned int id, GeoXF::Function* +nodePtr) { - m_memMapSerialTransformers.push_back(nodePtr); // vector, we store them in the order of IDs + m_memMapFunctions.push_back(nodePtr); // vector, we store them in the order of +IDs } -GeoSerialTransformer* ReadGeoModel::getBuiltSerialTransformer(const unsigned int id) +GeoXF::Function* ReadGeoModel::getBuiltFunction(const unsigned int id) { - return m_memMapSerialTransformers[id-1]; // remember: nodes' IDs start from 1 - -} - /* FIXME: - // --- methods for caching Functions nodes --- - bool ReadGeoModel::isBuiltFunction(const unsigned int id) - { - return (id <= m_memMapFunctions.size()); // vector: we exploit the fact that we built the vols ordered by their IDs - } - void ReadGeoModel::storeBuiltFunction(const unsigned int id, GeoXF::Function* nodePtr) - { - m_memMapFunctions.push_back(nodePtr); // vector, we store them in the order of IDs - - } - GeoXF::Function* ReadGeoModel::getBuiltFunction(const unsigned int id) - { - return m_memMapFunctions[id-1]; // remember: nodes' IDs start from 1 - } + return m_memMapFunctions[id-1]; // remember: nodes' IDs start from 1 +} */ // --- methods for caching GeoPhysVol/GeoFullPhysVol nodes --- -//std::string getVPhysVolKey(const unsigned int id, const unsigned int tableId, const unsigned int copyNumber) +// std::string getVPhysVolKey(const unsigned int id, const unsigned int tableId, +// const unsigned int copyNumber) //{ - //std::string key = std::to_string(id) + ":" + std::to_string(tableId) + ":" + std::to_string(copyNumber); - //return key; +// std::string key = std::to_string(id) + ":" + std::to_string(tableId) + ":" + +// std::to_string(copyNumber); return key; //} -std::string getVPhysVolKey(const unsigned int id, const unsigned int tableId) -{ - std::string key = std::to_string(id) + ":" + std::to_string(tableId); - return key; -} -//void ReadGeoModel::storeVPhysVol(const unsigned int id, const unsigned int tableId, const unsigned int copyN, GeoGraphNode* nodePtr) -void ReadGeoModel::storeVPhysVol(const unsigned int id, const unsigned int tableId, GeoGraphNode* nodePtr) -{ - std::lock_guard<std::mutex> lk(muxVPhysVol); - //std::string key = getVPhysVolKey(id, tableId, copyN); - std::string key = getVPhysVolKey(id, tableId); - m_memMap[key] = nodePtr; -} -//GeoGraphNode* ReadGeoModel::getVPhysVol(const unsigned int id, const unsigned int tableId, const unsigned int copyN) -GeoGraphNode* ReadGeoModel::getVPhysVol(const unsigned int id, const unsigned int tableId) -{ +std::string getVPhysVolKey(const unsigned int id, const unsigned int tableId) { + std::string key = std::to_string(id) + ":" + std::to_string(tableId); + return key; +} +// void ReadGeoModel::storeVPhysVol(const unsigned int id, const unsigned int +// tableId, const unsigned int copyN, GeoGraphNode* nodePtr) +void ReadGeoModel::storeVPhysVol(const unsigned int id, + const unsigned int tableId, + GeoGraphNode* nodePtr) { std::lock_guard<std::mutex> lk(muxVPhysVol); - //std::string key = getVPhysVolKey(id, tableId, copyN); - std::string key = getVPhysVolKey(id, tableId); - if (m_memMap.find(key) == m_memMap.end()) { - return nullptr; // if volume is not found in cache - } - return m_memMap[key]; + // std::string key = getVPhysVolKey(id, tableId, copyN); + std::string key = getVPhysVolKey(id, tableId); + m_memMap[key] = nodePtr; +} +// GeoGraphNode* ReadGeoModel::getVPhysVol(const unsigned int id, const unsigned +// int tableId, const unsigned int copyN) +GeoGraphNode* ReadGeoModel::getVPhysVol(const unsigned int id, + const unsigned int tableId) { + std::lock_guard<std::mutex> lk(muxVPhysVol); + // std::string key = getVPhysVolKey(id, tableId, copyN); + std::string key = getVPhysVolKey(id, tableId); + if (m_memMap.find(key) == m_memMap.end()) { + return nullptr; // if volume is not found in cache + } + return m_memMap[key]; } } /* namespace GeoModelIO */ diff --git a/GeoModelIO/GeoModelWrite/GeoModelWrite/WriteGeoModel.h b/GeoModelIO/GeoModelWrite/GeoModelWrite/WriteGeoModel.h index 4b37aa3d8de1e7239e9d8e6086ecb4fbf4da983e..a41d5e5cddd3e41ee88a8013dd2e3b0c87efe2e2 100644 --- a/GeoModelIO/GeoModelWrite/GeoModelWrite/WriteGeoModel.h +++ b/GeoModelIO/GeoModelWrite/GeoModelWrite/WriteGeoModel.h @@ -10,9 +10,16 @@ * - Feb 2019 - R.M.Bianchi * - May 2020 - R.M.Bianchi * - Aug 2020 - R.M.Bianchi // added support for GeoPublisher - * - Aug 2021 - Riccardo Maria Bianchi, <riccardo.maria.bianchi@cern.ch> - Added support for GeoSerialTransformer nodes -// - Jun 2022 - Riccardo Maria Bianchi, <riccardo.maria.bianchi@cern.ch>, -// Added support for "Verbose" output + * - Aug 2021 - Riccardo Maria Bianchi, <riccardo.maria.bianchi@cern.ch> + * Added support for GeoSerialTransformer nodes + * - Jun 2022 - Riccardo Maria Bianchi, <riccardo.maria.bianchi@cern.ch>, + * Added support for "Verbose" output + * - Jan 2023 - Riccardo Maria Bianchi, <riccardo.maria.bianchi@cern.ch>, + * Added the 'inspect' constructor to inspect + * the in-memory GeoModel tree, without saving to a .db file. + * Also added methods to get the numbers of visited nodes. + * - Feb 2023 - R.M.Bianchi <riccardo.maria.bianchi@cern.ch> + * Added 'setLoglevel' method, to steer output messages */ #ifndef GeoModelWrite_WriteGeoModel_H @@ -22,29 +29,34 @@ #include "GeoModelDBManager/GMDBManager.h" // GeoModel includes -#include "GeoModelKernel/GeoNodeAction.h" -#include "GeoModelKernel/GeoGraphNode.h" -#include "GeoModelKernel/GeoShape.h" +#include "GeoModelKernel/GeoAlignableTransform.h" +#include "GeoModelKernel/GeoDefinitions.h" #include "GeoModelKernel/GeoElement.h" -#include "GeoModelKernel/GeoMaterial.h" +#include "GeoModelKernel/GeoGraphNode.h" #include "GeoModelKernel/GeoLogVol.h" +#include "GeoModelKernel/GeoMaterial.h" +#include "GeoModelKernel/GeoNodeAction.h" +#include "GeoModelKernel/GeoShape.h" #include "GeoModelKernel/GeoXF.h" -#include "GeoModelKernel/GeoAlignableTransform.h" -#include "GeoModelKernel/GeoDefinitions.h" // C++ includes -#include <variant> -#include <vector> +#include <set> #include <string> #include <unordered_map> #include <utility> -#include <set> +#include <variant> +#include <vector> // FWD declarations class GeoPublisher; -typedef std::unordered_map<std::string, std::pair<std::vector<std::string>, std::vector<std::string>>> AuxTableDefs; -typedef std::unordered_map<std::string, std::vector<std::vector<std::variant<int,long,float,double,std::string>>>> AuxTableData; +typedef std::unordered_map< + std::string, std::pair<std::vector<std::string>, std::vector<std::string>>> + AuxTableDefs; +typedef std::unordered_map< + std::string, std::vector<std::vector< + std::variant<int, long, float, double, std::string>>>> + AuxTableData; namespace GeoModelIO { /** @@ -53,191 +65,306 @@ namespace GeoModelIO { * WriteGeoModel acts on objects of the GeoModel tree * persitifying them offline. */ -class WriteGeoModel : public GeoNodeAction -{ -public: - /** - * @brief Constructor - * - * Constructor sets up connection with db and opens it - * @param path - absolute path to db file - */ - WriteGeoModel(GMDBManager& db); - - /** - * @brief Destructor - */ - ~WriteGeoModel(); - - virtual void handlePhysVol (const GeoPhysVol *vol); // Handles a physical volume. - virtual void handleFullPhysVol (const GeoFullPhysVol *vol); // Handles a full physical volume. - virtual void handleSerialDenominator (const GeoSerialDenominator *sD); // Handles a Serial Denominator. - virtual void handleSerialTransformer (const GeoSerialTransformer *obj); // Handles a Serial Transformer - virtual void handleTransform (const GeoTransform *); // Handles a Transform. - virtual void handleNameTag (const GeoNameTag *); // Handles a Name Tag. - virtual void handleIdentifierTag (const GeoIdentifierTag *); // Handles an Identifier Tag. - virtual void handleSerialIdentifier(const GeoSerialIdentifier *); // Handles a SerialIdentifier. - - - //void storeDataTable( std::string tableName, std::vector<std::string> colNames, std::vector<std::string> colTypes, std::vector<std::vector<std::string>> tableData ); - void storeDataTable( std::string tableName, std::vector<std::string> colNames, std::vector<std::string> colTypes, std::vector<std::vector<std::variant<int,long,float,double,std::string>>> tableData ); - - void saveToDB(GeoPublisher* store = nullptr); - void saveToDB( std::vector<GeoPublisher*>& vecStores); - -private: - - // define copy constructor, needed for the GeoModelAction subclass - WriteGeoModel(const WriteGeoModel &right); - - // define assignment operator, needed for the GeoModelAction subclass - WriteGeoModel & operator=(const WriteGeoModel &right); - - void handleVPhysVolObjects(const GeoVPhysVol* vol); - void handleReferencedVPhysVol (const GeoVPhysVol *vol); // Handles a physical volume referenced by a SerialTrasformer - - void showMemoryMap(); - - std::vector<std::string> getParentNode(); - - unsigned int storeShape(const GeoShape* shape); - unsigned int storeMaterial(const GeoMaterial* mat); - unsigned int storeElement(const GeoElement* el); - unsigned int storeTranform(const GeoTransform* node); - - unsigned int storeObj(const GeoMaterial* pointer, const std::string &name, const double &density, const std::string &elements); - unsigned int storeObj(const GeoElement* pointer, const std::string &name, const std::string &symbol, const double &elZ, const double &elA); - unsigned int storeObj(const GeoShape* pointer, const std::string &type, const std::string ¶meters); - unsigned int storeObj(const GeoLogVol* pointer, const std::string &name, const unsigned int &shapeId, const unsigned int &materialId); - unsigned int storeObj(const GeoPhysVol* pointer, const unsigned int &logvolId, const unsigned int parentId = 0, const bool isRootVolume = false ); - unsigned int storeObj(const GeoFullPhysVol* pointer, const unsigned int &logvolId, const unsigned int parentId = 0, const bool isRootVolume = false ); - unsigned int storeObj(const GeoSerialDenominator* pointer, const std::string &baseName); - unsigned int storeObj(const GeoSerialIdentifier* pointer, const int &baseId); - unsigned int storeObj(const GeoIdentifierTag* pointer, const int &identifier); - unsigned int storeObj(const GeoSerialTransformer* pointer, const unsigned int &functionId, const unsigned int &volId, const std::string &volType, const unsigned int &copies); - unsigned int storeObj(const GeoXF::Function* pointer, const std::string &expression); - unsigned int storeObj(const GeoTransform* pointer, const std::vector<double> ¶meters); - unsigned int storeObj(const GeoAlignableTransform* pointer, const std::vector<double> ¶meters); - unsigned int storeObj(const GeoNameTag* pointer, const std::string &name); - - unsigned int addRecord(std::vector<std::vector<std::string>>* container, const std::vector<std::string> values) const; - - unsigned int addMaterial(const std::string &name, const double &density, const std::string &elements); - unsigned int addElement(const std::string &name, const std::string &symbol, const double &elZ, const double &elA); - unsigned int addNameTag(const std::string &name); - unsigned int addAlignableTransform(const std::vector<double> ¶ms); - unsigned int addTransform(const std::vector<double> ¶ms); - unsigned int addFunction(const std::string &expression); - unsigned int addSerialTransformer(const unsigned int &funcId, const unsigned int &physvolId, const std::string volType, const unsigned int &copies); - unsigned int addShape(const std::string &type, const std::string ¶meters); - unsigned int addSerialDenominator(const std::string &baseName); - unsigned int addSerialIdentifier(const int &baseId); - unsigned int addIdentifierTag(const int &identifier); - unsigned int addPhysVol(const unsigned int &logVolId, const unsigned int &parentPhysVolId, const bool &isRootVolume); - unsigned int addFullPhysVol(const unsigned int &logVolId, const unsigned int &parentPhysVolId, const bool &isRootVolume); - unsigned int addLogVol(const std::string &name, const unsigned int &shapeId, const unsigned int &materialId); - void addChildPosition(const unsigned int &parentId, const std::string &parentType, const unsigned int &childId, const unsigned int &parentCopyNumber, const unsigned int &childPos, const std::string &childType, const unsigned int &childCopyN); - - unsigned int getChildPosition(const unsigned int &parentId, const std::string &parentType, const unsigned int ©N); - - unsigned int setVolumeCopyNumber(const unsigned int& volId, const std::string& volType); - unsigned int getLatestParentCopyNumber(const unsigned int& parentId, const std::string& parentType); - - void storeChildPosition(const unsigned int& parentId, const std::string& parentType, const unsigned int& childVol, const unsigned int& parentCopyNumber, const unsigned int& childPos, const std::string& childType, const unsigned int& childCopyN); - - bool isAddressStored(const std::string &address); - void storeAddress(const std::string &address, const unsigned int &id); - - unsigned int getStoredIdFromAddress(const std::string &address); - - std::string getAddressStringFromPointer(const GeoMaterial* pointer); - std::string getAddressStringFromPointer(const GeoElement* pointer); - std::string getAddressStringFromPointer(const GeoShape* pointer); - std::string getAddressStringFromPointer(const GeoLogVol* pointer); - std::string getAddressStringFromPointer(const GeoPhysVol* pointer); - std::string getAddressStringFromPointer(const GeoVPhysVol* pointer); - std::string getAddressStringFromPointer(const GeoSerialDenominator* pointer); - std::string getAddressStringFromPointer(const GeoSerialIdentifier* pointer); - std::string getAddressStringFromPointer(const GeoIdentifierTag* pointer); - std::string getAddressStringFromPointer(const GeoSerialTransformer* pointer); - std::string getAddressStringFromPointer(const GeoXF::Function* pointer); - std::string getAddressStringFromPointer(const GeoTransform* pointer); - std::string getAddressStringFromPointer(const GeoNameTag* pointer); - - std::string getQStringFromOss(std::ostringstream &oss); - - std::vector<double> getTransformParameters(GeoTrf::Transform3D); // TODO: to be moved to Eigen (GeoTrf) and to be moved to an Utility class, so we can use it from TransFunctionRecorder as well. - std::string getShapeParameters(const GeoShape*); - - std::string getGeoTypeFromVPhysVol(const GeoVPhysVol* vol); - - unsigned int getIdFromNodeType(const std::string &nodeType); - - void storePublishedNodes(GeoPublisher* store); - template <typename TT> void storeRecordPublishedNodes(const TT storeMap, std::vector<std::vector<std::string>>* cachePublishedNodes); - - void storePublishedAuxiliaryData(GeoPublisher* store); - - std::string m_dbpath; - GMDBManager* m_dbManager; +class WriteGeoModel : public GeoNodeAction { + public: + /** + * @brief Constructor + * + * Constructor sets up connection with db and opens it + * @param path - absolute path to db file + */ + WriteGeoModel(GMDBManager &db); + + /** + * @brief 'Inspect' Contructor, it does not save to the DB + */ + WriteGeoModel() { m_inspect = true; }; + + /** + * @brief Destructor + */ + ~WriteGeoModel(); + + /// Set the 'loglevel', that is the level of output messages. + /// The loglevel is set to 0 by default, but it can be set + /// to a larger value. + /// Loglevel: + /// - 0 : Default + /// - 1 : Verbose + /// - 2 : Debug + void setLogLevel(unsigned loglevel) { m_loglevel = loglevel; }; + + virtual void handlePhysVol( + const GeoPhysVol *vol); // Handles a physical volume. + virtual void handleFullPhysVol( + const GeoFullPhysVol *vol); // Handles a full physical volume. + virtual void handleSerialDenominator( + const GeoSerialDenominator *sD); // Handles a Serial Denominator. + virtual void handleSerialTransformer( + const GeoSerialTransformer *obj); // Handles a Serial Transformer + virtual void handleTransform(const GeoTransform *); // Handles a + // Transform. + virtual void handleNameTag(const GeoNameTag *); // Handles a Name Tag. + virtual void handleIdentifierTag( + const GeoIdentifierTag *); // Handles an Identifier Tag. + virtual void handleSerialIdentifier( + const GeoSerialIdentifier *); // Handles a SerialIdentifier. + + // void storeDataTable( std::string tableName, std::vector<std::string> + // colNames, std::vector<std::string> colTypes, + // std::vector<std::vector<std::string>> tableData ); + void storeDataTable( + std::string tableName, std::vector<std::string> colNames, + std::vector<std::string> colTypes, + std::vector< + std::vector<std::variant<int, long, float, double, std::string>>> + tableData); + + void saveToDB(GeoPublisher *store = nullptr); + void saveToDB(std::vector<GeoPublisher *> &vecStores); + + unsigned long getNLogVols() { return m_logVols.size(); }; + unsigned long getNPhysVols() { return m_physVols.size(); }; + unsigned long getNFullPhysVols() { return m_fullPhysVols.size(); }; + unsigned long getNMaterials() { return m_materials.size(); }; + unsigned long getNElements() { return m_elements.size(); }; + unsigned long getNTransforms() { return m_transforms.size(); }; + unsigned long getNAlignableTransforms() { + return m_alignableTransforms.size(); + }; + unsigned long getNSerialDenominators() { + return m_serialDenominators.size(); + }; + unsigned long getNSerialIdentifiers() { + return m_serialIdentifiers.size(); + }; + unsigned long getNIdentifierTags() { return m_identifierTags.size(); }; + unsigned long getNSerialTransformers() { + return m_serialTransformers.size(); + }; + unsigned long getNFunctions() { return m_functions.size(); }; + unsigned long getNNameTags() { return m_nameTags.size(); }; + unsigned long getNShapes() { return m_shapes.size(); }; + unsigned long getNChildrenConnections() { + return m_childrenPositions.size(); + }; + + private: + // define copy constructor, needed for the GeoModelAction subclass + WriteGeoModel(const WriteGeoModel &right); + + // define assignment operator, needed for the GeoModelAction subclass + WriteGeoModel &operator=(const WriteGeoModel &right); + + void handleVPhysVolObjects(const GeoVPhysVol *vol); + + /// Handles a physical volume referenced by a SerialTrasformer + void handleReferencedVPhysVol(const GeoVPhysVol *vol); + + void showMemoryMap(); + + std::vector<std::string> getParentNode(); + + unsigned int storeShape(const GeoShape *shape); + unsigned int storeMaterial(const GeoMaterial *mat); + unsigned int storeElement(const GeoElement *el); + unsigned int storeTranform(const GeoTransform *node); + + unsigned int storeObj(const GeoMaterial *pointer, const std::string &name, + const double &density, const std::string &elements); + unsigned int storeObj(const GeoElement *pointer, const std::string &name, + const std::string &symbol, const double &elZ, + const double &elA); + unsigned int storeObj(const GeoShape *pointer, const std::string &type, + const std::string ¶meters); + unsigned int storeObj(const GeoLogVol *pointer, const std::string &name, + const unsigned int &shapeId, + const unsigned int &materialId); + unsigned int storeObj(const GeoPhysVol *pointer, + const unsigned int &logvolId, + const unsigned int parentId = 0, + const bool isRootVolume = false); + unsigned int storeObj(const GeoFullPhysVol *pointer, + const unsigned int &logvolId, + const unsigned int parentId = 0, + const bool isRootVolume = false); + unsigned int storeObj(const GeoSerialDenominator *pointer, + const std::string &baseName); + unsigned int storeObj(const GeoSerialIdentifier *pointer, + const int &baseId); + unsigned int storeObj(const GeoIdentifierTag *pointer, + const int &identifier); + unsigned int storeObj(const GeoSerialTransformer *pointer, + const unsigned int &functionId, + const unsigned int &volId, const std::string &volType, + const unsigned int &copies); + unsigned int storeObj(const GeoXF::Function *pointer, + const std::string &expression); + unsigned int storeObj(const GeoTransform *pointer, + const std::vector<double> ¶meters); + unsigned int storeObj(const GeoAlignableTransform *pointer, + const std::vector<double> ¶meters); + unsigned int storeObj(const GeoNameTag *pointer, const std::string &name); + + unsigned int addRecord(std::vector<std::vector<std::string>> *container, + const std::vector<std::string> values) const; + + unsigned int addMaterial(const std::string &name, const double &density, + const std::string &elements); + unsigned int addElement(const std::string &name, const std::string &symbol, + const double &elZ, const double &elA); + unsigned int addNameTag(const std::string &name); + unsigned int addAlignableTransform(const std::vector<double> ¶ms); + unsigned int addTransform(const std::vector<double> ¶ms); + unsigned int addFunction(const std::string &expression); + unsigned int addSerialTransformer(const unsigned int &funcId, + const unsigned int &physvolId, + const std::string volType, + const unsigned int &copies); + unsigned int addShape(const std::string &type, + const std::string ¶meters); + unsigned int addSerialDenominator(const std::string &baseName); + unsigned int addSerialIdentifier(const int &baseId); + unsigned int addIdentifierTag(const int &identifier); + unsigned int addPhysVol(const unsigned int &logVolId, + const unsigned int &parentPhysVolId, + const bool &isRootVolume); + unsigned int addFullPhysVol(const unsigned int &logVolId, + const unsigned int &parentPhysVolId, + const bool &isRootVolume); + unsigned int addLogVol(const std::string &name, const unsigned int &shapeId, + const unsigned int &materialId); + void addChildPosition(const unsigned int &parentId, + const std::string &parentType, + const unsigned int &childId, + const unsigned int &parentCopyNumber, + const unsigned int &childPos, + const std::string &childType, + const unsigned int &childCopyN); + + unsigned int getChildPosition(const unsigned int &parentId, + const std::string &parentType, + const unsigned int ©N); + + unsigned int setVolumeCopyNumber(const unsigned int &volId, + const std::string &volType); + unsigned int getLatestParentCopyNumber(const unsigned int &parentId, + const std::string &parentType); + + void storeChildPosition(const unsigned int &parentId, + const std::string &parentType, + const unsigned int &childVol, + const unsigned int &parentCopyNumber, + const unsigned int &childPos, + const std::string &childType, + const unsigned int &childCopyN); + + bool isAddressStored(const std::string &address); + void storeAddress(const std::string &address, const unsigned int &id); + + unsigned int getStoredIdFromAddress(const std::string &address); + + std::string getAddressStringFromPointer(const GeoMaterial *pointer); + std::string getAddressStringFromPointer(const GeoElement *pointer); + std::string getAddressStringFromPointer(const GeoShape *pointer); + std::string getAddressStringFromPointer(const GeoLogVol *pointer); + std::string getAddressStringFromPointer(const GeoPhysVol *pointer); + std::string getAddressStringFromPointer(const GeoVPhysVol *pointer); + std::string getAddressStringFromPointer( + const GeoSerialDenominator *pointer); + std::string getAddressStringFromPointer(const GeoSerialIdentifier *pointer); + std::string getAddressStringFromPointer(const GeoIdentifierTag *pointer); + std::string getAddressStringFromPointer( + const GeoSerialTransformer *pointer); + std::string getAddressStringFromPointer(const GeoXF::Function *pointer); + std::string getAddressStringFromPointer(const GeoTransform *pointer); + std::string getAddressStringFromPointer(const GeoNameTag *pointer); + + std::string getQStringFromOss(std::ostringstream &oss); + + std::vector<double> getTransformParameters( + GeoTrf::Transform3D); // TODO: to be moved to Eigen (GeoTrf) and to be + // moved to an Utility class, so we can use it + // from TransFunctionRecorder as well. + std::string getShapeParameters(const GeoShape *); + + std::string getGeoTypeFromVPhysVol(const GeoVPhysVol *vol); + + unsigned int getIdFromNodeType(const std::string &nodeType); + + void storePublishedNodes(GeoPublisher *store); + template <typename TT> + void storeRecordPublishedNodes( + const TT storeMap, + std::vector<std::vector<std::string>> *cachePublishedNodes); + + void storePublishedAuxiliaryData(GeoPublisher *store); + + std::string m_dbpath; + GMDBManager *m_dbManager; // work caches - std::set<std::string> m_linkSet; - std::unordered_map<std::string, unsigned int> m_parentChildrenMap; - std::unordered_map<std::string, unsigned int> m_volumeCopiesMap; - std::unordered_map<std::string, unsigned int> m_memMap; - std::unordered_map<std::string, unsigned int> m_memMap_Tables; + std::set<std::string> m_linkSet; + std::unordered_map<std::string, unsigned int> m_parentChildrenMap; + std::unordered_map<std::string, unsigned int> m_volumeCopiesMap; + std::unordered_map<std::string, unsigned int> m_memMap; + std::unordered_map<std::string, unsigned int> m_memMap_Tables; - // keep track of the number of visited tree node - unsigned int m_len; - unsigned int m_len_nChild; + // keep track of the number of visited tree node + unsigned int m_len; + unsigned int m_len_nChild; // store True if we have found the Root volume - bool m_rootVolumeFound; - - // store True if we are visiting an unconnected tree + bool m_rootVolumeFound; + + // store True if we are visiting an unconnected tree // (for example, one used in a GeoSerialTransformer) - bool m_unconnectedTree; + bool m_unconnectedTree; // caches for GeoModel nodes to be saved into the DB - std::vector<std::vector<std::string>> m_logVols; - std::vector<std::vector<std::string>> m_physVols; - std::vector<std::vector<std::string>> m_fullPhysVols; - std::vector<std::vector<std::string>> m_materials; - std::vector<std::vector<std::string>> m_elements; - std::vector<std::vector<std::string>> m_transforms; - std::vector<std::vector<std::string>> m_alignableTransforms; - std::vector<std::vector<std::string>> m_serialDenominators; - std::vector<std::vector<std::string>> m_serialIdentifiers; - std::vector<std::vector<std::string>> m_identifierTags; - std::vector<std::vector<std::string>> m_serialTransformers; - std::vector<std::vector<std::string>> m_functions; - std::vector<std::vector<std::string>> m_nameTags; - std::vector<std::vector<std::string>> m_shapes; - + std::vector<std::vector<std::string>> m_logVols; + std::vector<std::vector<std::string>> m_physVols; + std::vector<std::vector<std::string>> m_fullPhysVols; + std::vector<std::vector<std::string>> m_materials; + std::vector<std::vector<std::string>> m_elements; + std::vector<std::vector<std::string>> m_transforms; + std::vector<std::vector<std::string>> m_alignableTransforms; + std::vector<std::vector<std::string>> m_serialDenominators; + std::vector<std::vector<std::string>> m_serialIdentifiers; + std::vector<std::vector<std::string>> m_identifierTags; + std::vector<std::vector<std::string>> m_serialTransformers; + std::vector<std::vector<std::string>> m_functions; + std::vector<std::vector<std::string>> m_nameTags; + std::vector<std::vector<std::string>> m_shapes; + // caches for Metadata to be saved into the DB std::vector<std::string> m_rootVolume; - std::vector<std::vector<std::string>> m_childrenPositions; - std::vector<std::vector<std::string>> m_publishedAlignableTransforms_String; - std::vector<std::vector<std::string>> m_publishedFullPhysVols_String; - - // cache to store custom tables to store auxiliary data in the DB: - // ---> map( tableName, columnsNames, columnsTypes ) - //std::unordered_map<std::string, std::pair<std::vector<std::string>, std::vector<std::string>>> m_auxiliaryTablesStr; - AuxTableDefs m_auxiliaryTablesVar; - //std::unordered_map<std::string, std::vector<std::vector<std::string>>> m_auxiliaryTablesStrData; - AuxTableData m_auxiliaryTablesVarData; - - - // cache to store the node that could not have persistified. + std::vector<std::vector<std::string>> m_childrenPositions; + std::vector<std::vector<std::string>> m_publishedAlignableTransforms_String; + std::vector<std::vector<std::string>> m_publishedFullPhysVols_String; + + // cache to store custom tables to store auxiliary data in the DB: + // ---> map( tableName, columnsNames, columnsTypes ) + // std::unordered_map<std::string, std::pair<std::vector<std::string>, + // std::vector<std::string>>> m_auxiliaryTablesStr; + AuxTableDefs m_auxiliaryTablesVar; + // std::unordered_map<std::string, std::vector<std::vector<std::string>>> + // m_auxiliaryTablesStrData; + AuxTableData m_auxiliaryTablesVarData; + + // cache to store the node that could not have persistified. // Usually, that means that persistification code has not been developed // for the particular GeoModel node - std::vector<std::string> m_objectsNotPersistified; + std::vector<std::string> m_objectsNotPersistified; - // verbosity level - int m_verbose; + // inpect-only mode, no DB writing + // it is set to 'true' when the overloaded 'inspect' constructor is called + // instead of the 'db' constructor + bool m_inspect{0}; + /// Stores the loglevel, the verbosity of the output messages + unsigned m_loglevel; }; } /* namespace GeoModelIO */ -#endif // GeoModelWrite_WriteGeoModel_H +#endif // GeoModelWrite_WriteGeoModel_H diff --git a/GeoModelIO/GeoModelWrite/src/WriteGeoModel.cpp b/GeoModelIO/GeoModelWrite/src/WriteGeoModel.cpp index c6343060b314732fdf48c2b4f57302fdbdd49979..bb89ccaad0a12b0ff46fdc68afbbb00ad2cb32fd 100644 --- a/GeoModelIO/GeoModelWrite/src/WriteGeoModel.cpp +++ b/GeoModelIO/GeoModelWrite/src/WriteGeoModel.cpp @@ -16,7 +16,12 @@ // Added support for GeoSerialTransformer nodes // - Jun 2022 - Riccardo Maria Bianchi, <riccardo.maria.bianchi@cern.ch>, // Added support for "Verbose" output - +// - Feb 2023 - R.M.Bianchi <riccardo.maria.bianchi@cern.ch> +// Added 'setLoglevel' method, to steer output messages +// - Nov 2023 - R.M.Bianchi <riccardo.maria.bianchi@cern.ch> +// Updated to use the AlignableTransform 'default position', +// which does not include alignment constants +// // local includes #include "GeoModelWrite/WriteGeoModel.h" @@ -28,349 +33,371 @@ // #include "GeoSpecialShapes/LArCustomShape.h" // GeoModelKernel includes -#include "GeoModelKernel/GeoNodePath.h" #include "GeoModelKernel/GeoCountVolAction.h" +#include "GeoModelKernel/GeoNodePath.h" // GeoModelKernel shapes #include "GeoModelKernel/GeoBox.h" #include "GeoModelKernel/GeoCons.h" +#include "GeoModelKernel/GeoGenericTrap.h" #include "GeoModelKernel/GeoPara.h" #include "GeoModelKernel/GeoPcon.h" #include "GeoModelKernel/GeoPgon.h" +#include "GeoModelKernel/GeoPublisher.h" +#include "GeoModelKernel/GeoShapeIntersection.h" +#include "GeoModelKernel/GeoShapeShift.h" +#include "GeoModelKernel/GeoShapeSubtraction.h" +#include "GeoModelKernel/GeoShapeUnion.h" #include "GeoModelKernel/GeoSimplePolygonBrep.h" #include "GeoModelKernel/GeoTessellatedSolid.h" +#include "GeoModelKernel/GeoTorus.h" #include "GeoModelKernel/GeoTrap.h" -#include "GeoModelKernel/GeoTwistedTrap.h" #include "GeoModelKernel/GeoTrd.h" #include "GeoModelKernel/GeoTube.h" #include "GeoModelKernel/GeoTubs.h" -#include "GeoModelKernel/GeoGenericTrap.h" -#include "GeoModelKernel/GeoTorus.h" -#include "GeoModelKernel/GeoShapeIntersection.h" -#include "GeoModelKernel/GeoShapeShift.h" -#include "GeoModelKernel/GeoShapeSubtraction.h" -#include "GeoModelKernel/GeoShapeUnion.h" -#include "GeoModelKernel/GeoPublisher.h" - +#include "GeoModelKernel/GeoTwistedTrap.h" #include "GeoModelKernel/GeoUnidentifiedShape.h" // C++ includes #include <sstream> - namespace GeoModelIO { - // TODO: should go to an utility class - // FIXME: should go to an utility class - std::string joinVectorStrings(std::vector<std::string> vec, std::string sep="") { +// TODO: should go to an utility class +// FIXME: should go to an utility class +std::string joinVectorStrings(std::vector<std::string> vec, + std::string sep = "") { std::string s; unsigned int ii = 0; - for (const auto &piece : vec) { - ++ii; - if (ii == vec.size()) { - s += (piece); - } else { - s += (piece + sep); - } + for (const auto& piece : vec) { + ++ii; + if (ii == vec.size()) { + s += (piece); + } else { + s += (piece + sep); + } } return s; - } - - // TODO: move this to utility class/file - void printStdVectorStrings(std::vector<std::string> vec) - { - for ( const auto& str : vec) { - std::cout << str << " "; +} + +// TODO: move this to utility class/file +void printStdVectorStrings(std::vector<std::string> vec) { + for (const auto& str : vec) { + std::cout << str << " "; } std::cout << std::endl; return; - } +} -// Function to increase the precision of the conversion from double to string - used in the write operation -std::string to_string_with_precision(const double a_value, const int n = 16){ - +// Function to increase the precision of the conversion from double to string - +// used in the write operation +std::string to_string_with_precision(const double a_value, const int n = 16) { std::ostringstream out; out.precision(n); out << std::fixed << a_value; return out.str(); } - + /// Get next child position available, given the parent type, id and copy number - unsigned int WriteGeoModel::getChildPosition(const unsigned int &parentId, const std::string &parentType, const unsigned int ©N) -{ - unsigned int tableId = getIdFromNodeType(parentType); - //INT - std::string key = std::to_string(tableId) + ":" + std::to_string(parentId) + ":" + std::to_string(copyN); //INT - - std::unordered_map<std::string, unsigned int>::iterator it = m_parentChildrenMap.find(key); - if ( it == m_parentChildrenMap.end() ) { - m_parentChildrenMap[key] = 1; // if item is not present, create an entry - } else { - ++m_parentChildrenMap[key]; // if present already, then increment its entry +unsigned int WriteGeoModel::getChildPosition(const unsigned int& parentId, + const std::string& parentType, + const unsigned int& copyN) { + unsigned int tableId = getIdFromNodeType(parentType); + // INT + std::string key = std::to_string(tableId) + ":" + std::to_string(parentId) + + ":" + std::to_string(copyN); // INT + + std::unordered_map<std::string, unsigned int>::iterator it = + m_parentChildrenMap.find(key); + if (it == m_parentChildrenMap.end()) { + m_parentChildrenMap[key] = + 1; // if item is not present, create an entry + } else { + ++m_parentChildrenMap[key]; // if present already, then increment its + // entry } - return m_parentChildrenMap[key]; + return m_parentChildrenMap[key]; } - unsigned int WriteGeoModel::setVolumeCopyNumber(const unsigned int& volId, const std::string& volType) -{ - //JFB Commented out: qDebug() << "WriteGeoModel::setVolumeCopyNumber()"; - const unsigned int tableId = getIdFromNodeType(volType); - std::string key = std::to_string(tableId) + ":" + std::to_string(volId); //INT +unsigned int WriteGeoModel::setVolumeCopyNumber(const unsigned int& volId, + const std::string& volType) { + // JFB Commented out: qDebug() << "WriteGeoModel::setVolumeCopyNumber()"; + const unsigned int tableId = getIdFromNodeType(volType); + std::string key = + std::to_string(tableId) + ":" + std::to_string(volId); // INT - std::unordered_map<std::string, unsigned int>::iterator it = m_volumeCopiesMap.find(key); - if ( it == m_volumeCopiesMap.end() ) { - m_volumeCopiesMap[key] = 1; - } else { - ++m_volumeCopiesMap[key]; + std::unordered_map<std::string, unsigned int>::iterator it = + m_volumeCopiesMap.find(key); + if (it == m_volumeCopiesMap.end()) { + m_volumeCopiesMap[key] = 1; + } else { + ++m_volumeCopiesMap[key]; } - return m_volumeCopiesMap[key]; + return m_volumeCopiesMap[key]; } +unsigned int WriteGeoModel::getLatestParentCopyNumber( + const unsigned int& parentId, const std::string& parentType) { + const unsigned int tableId = getIdFromNodeType(parentType); + std::string key = + std::to_string(tableId) + ":" + std::to_string(parentId); // INT - unsigned int WriteGeoModel::getLatestParentCopyNumber(const unsigned int &parentId, const std::string &parentType) -{ - const unsigned int tableId = getIdFromNodeType(parentType); - std::string key = std::to_string(tableId) + ":" + std::to_string(parentId); //INT - - std::unordered_map<std::string, unsigned int>::iterator it = m_volumeCopiesMap.find(key); - if ( it == m_volumeCopiesMap.end() ) { - std::cout << "ERROR!!! Something's wrong in storing the number of copies!" << std::endl; - } - return m_volumeCopiesMap[key]; + std::unordered_map<std::string, unsigned int>::iterator it = + m_volumeCopiesMap.find(key); + if (it == m_volumeCopiesMap.end()) { + std::cout + << "ERROR!!! Something's wrong in storing the number of copies!" + << std::endl; + } + return m_volumeCopiesMap[key]; } - -void WriteGeoModel::handlePhysVol (const GeoPhysVol *vol) -{ - handleVPhysVolObjects( vol ); +void WriteGeoModel::handlePhysVol(const GeoPhysVol* vol) { + handleVPhysVolObjects(vol); } - -void WriteGeoModel::handleFullPhysVol (const GeoFullPhysVol *vol) -{ - handleVPhysVolObjects( vol ); +void WriteGeoModel::handleFullPhysVol(const GeoFullPhysVol* vol) { + handleVPhysVolObjects(vol); } +void WriteGeoModel::handleVPhysVolObjects(const GeoVPhysVol* vol) { + if (m_loglevel >= 2) { + std::cout << "WriteGeoModel::handleVPhysVolObjects() -- visiting... " + << vol << std::endl; + } + // get the address string for the current volume + std::string address = getAddressStringFromPointer(vol); -void WriteGeoModel::handleVPhysVolObjects(const GeoVPhysVol* vol) -{ - //std::cout << "WriteGeoModel::handleVPhysVolObjects() -- visiting... " << vol << std::endl; // debug msg - - // get the address string for the current volume - std::string address = getAddressStringFromPointer( vol ); - - // variables used to persistify the object - unsigned int physId; + // variables used to persistify the object + unsigned int physId; - // check the volume position in the geometry tree - GeoNodePath* path = getPath(); - unsigned int len = path->getLength(); -// const GeoVPhysVol* tailVol = path->getTail(); -// const GeoVPhysVol* headVol = path->getHead(); + // check the volume position in the geometry tree + GeoNodePath* path = getPath(); + unsigned int len = path->getLength(); + // const GeoVPhysVol* tailVol = path->getTail(); + // const GeoVPhysVol* headVol = path->getHead(); const GeoVPhysVol* upperVol = nullptr; if (len > 1) - upperVol = path->getItem(len-2); // item(len-1) is THIS volume ==> the length is updated when visiting a VPhysVol node + upperVol = path->getItem( + len - 2); // item(len-1) is THIS volume ==> the length is updated + // when visiting a VPhysVol node else - upperVol = path->getItem(len-1); // ROOT volume - //JFB Commented out: qDebug() << "path: " << path << " - length: " << len << " - upper vol: " << upperVol << " - tail vol: " << tailVol << " - head vol: " << headVol; - // std::cout << "path: " << path << std::endl; - - // this below is performed until the root volume is found, then "length" is not used anymore, - // because not updated when recursively visiting children of PhysVols: it is updated only when a PhysVol node is visited - - bool doGetParentNode = true; - bool storeRootVolume = false; - bool isRootVolume = false; - - - if ( ! m_rootVolumeFound) { - if (len > 1) { - doGetParentNode = true; // TODO: is that needed???? - } else{ - isRootVolume = true; - m_rootVolumeFound = true; - storeRootVolume = true; - doGetParentNode = false; - } - } else { - doGetParentNode = true; - } - - // When dumping an unconnected sub-tree, e.g. a PhysVol used only in a SerialTransformer, - // we don't want to get the parent ID. - // If we do, the ID of the parent of the SerialTransformer is returned, which is wrong. - if (m_unconnectedTree) { - doGetParentNode = false; - //qDebug() << "Handling an unconnected tree: we skip the parent-finding step..."; - // now, we reset the status, - // otherwise all the children of the first referenced, unconnected volume - // will be treated as unconnected as well - //qDebug() << "setting 'unconnected' to: false"; - m_unconnectedTree = false; - } - - - // // get the parent volume - // QStringList parentList = getParentNode(); // you can use that, but you have to modify it to get len-2, instead of len-1, for VPhysVol nodes - // QString parentId = parentList[0]; - // QString parentType = parentList[1]; - - // get the parent volume, if this is not the Root volume or an unconnected sub-tree - const GeoVPhysVol* parentNode = nullptr; - unsigned int parentId = 0; - - std::string volTypeStr = "0"; - - if (doGetParentNode) { - -// bool isShared = vol->isShared(); - //qDebug() << "is this node shared?" << isShared; - - //if (isShared) - parentNode = upperVol; - //else - // parentNode = dynamic_cast<const GeoVPhysVol*>( &(*(vol->getParent() ))); // this cannot be trust for shared nodes - //qDebug() << "parentNode address" << parentNode; - - if (parentNode) { - std::string parentAddress = getAddressStringFromPointer(parentNode); - //JFB Commented out: qDebug() << "==> parent's address:" << parentNode; - - if (isAddressStored(parentAddress)) - parentId = getStoredIdFromAddress(parentAddress); - // else - // qFatal("FATAL ERROR!!! - The parent node of this child should has been stored in the DB already, but it was not found!!"); - - //qDebug() << "==> parent's LogVol name:" << QString::fromStdString(parentNode->getLogVol()->getName()); - } - else { - //qDebug() << "NULL parent node!! --> this node appeared unconnected."; - } - } - - // counting children -// unsigned int nChildren = vol->getNChildVols(); - //qDebug() << "number of child physical volumes:" << nChildren; - //qDebug() << "[number of PhysVol and SerialTransformer child nodes:" << vol->getNChildVolAndST() << "]"; - - //// for debug - // GeoCountVolAction cv; - // cv.setDepthLimit(1); - // vol->exec(&cv); - // int nChildCount = cv.getCount(); - // qDebug() << "number of child volumes:" << nChildCount; - - - - // check if this object has been stored already - if (! isAddressStored(address)) { - - /* - * VPhysVol features: - * - 1 parent VPhysVol (if any) - * - 1 LogVol - * - 1 Material - * - 1 Shape - */ - - // Note: PhysVol has no name. Its LogVol has a name. - // const std::string name = vol->getLogVol()->getName(); - - // LOGVOL - const GeoLogVol* logVol = vol->getLogVol(); + upperVol = path->getItem(len - 1); // ROOT volume + // JFB Commented out: qDebug() << "path: " << path << " - length: " << len + // << " - upper vol: " << upperVol << " - tail vol: " << tailVol << " - head + // vol: " << headVol; std::cout << "path: " << path << std::endl; + + // this below is performed until the root volume is found, then "length" is + // not used anymore, because not updated when recursively visiting children + // of PhysVols: it is updated only when a PhysVol node is visited + + bool doGetParentNode = true; + bool storeRootVolume = false; + bool isRootVolume = false; + + if (!m_rootVolumeFound) { + if (len > 1) { + doGetParentNode = true; // TODO: is that needed???? + } else { + isRootVolume = true; + m_rootVolumeFound = true; + storeRootVolume = true; + doGetParentNode = false; + } + } else { + doGetParentNode = true; + } + + // When dumping an unconnected sub-tree, e.g. a PhysVol used only in a + // SerialTransformer, we don't want to get the parent ID. If we do, the ID + // of the parent of the SerialTransformer is returned, which is wrong. + if (m_unconnectedTree) { + doGetParentNode = false; + // qDebug() << "Handling an unconnected tree: we skip the parent-finding + // step..."; + // now, we reset the status, + // otherwise all the children of the first referenced, unconnected + // volume will be treated as unconnected as well + // qDebug() << "setting 'unconnected' to: false"; + m_unconnectedTree = false; + } + + // // get the parent volume + // QStringList parentList = getParentNode(); // you can use that, but you + // have to modify it to get len-2, instead of len-1, for VPhysVol nodes + // QString parentId = parentList[0]; + // QString parentType = parentList[1]; + + // get the parent volume, if this is not the Root volume or an unconnected + // sub-tree + const GeoVPhysVol* parentNode = nullptr; + unsigned int parentId = 0; + + std::string volTypeStr = "0"; + + if (doGetParentNode) { + // bool isShared = vol->isShared(); + // qDebug() << "is this node shared?" << isShared; + + // if (isShared) + parentNode = upperVol; + // else + // parentNode = dynamic_cast<const GeoVPhysVol*>( + // &(*(vol->getParent() ))); // this cannot be trust for shared + // nodes + // qDebug() << "parentNode address" << parentNode; + + if (parentNode) { + std::string parentAddress = getAddressStringFromPointer(parentNode); + // JFB Commented out: qDebug() << "==> parent's address:" << + // parentNode; + + if (isAddressStored(parentAddress)) + parentId = getStoredIdFromAddress(parentAddress); + // else + // qFatal("FATAL ERROR!!! - The parent node of this + // child should has been stored in the DB already, but it was not + // found!!"); + + // qDebug() << "==> parent's LogVol name:" << + // QString::fromStdString(parentNode->getLogVol()->getName()); + } else { + // qDebug() << "NULL parent node!! --> this node appeared + // unconnected."; + } + } + + // counting children + // unsigned int nChildren = vol->getNChildVols(); + // qDebug() << "number of child physical volumes:" << nChildren; + // qDebug() << "[number of PhysVol and SerialTransformer child nodes:" << + // vol->getNChildVolAndST() << "]"; + + //// for debug + // GeoCountVolAction cv; + // cv.setDepthLimit(1); + // vol->exec(&cv); + // int nChildCount = cv.getCount(); + // qDebug() << "number of child volumes:" << nChildCount; + + // check if this object has been stored already + if (!isAddressStored(address)) { + /* + * VPhysVol features: + * - 1 parent VPhysVol (if any) + * - 1 LogVol + * - 1 Material + * - 1 Shape + */ + + // Note: PhysVol has no name. Its LogVol has a name. + // const std::string name = vol->getLogVol()->getName(); + + // LOGVOL + const GeoLogVol* logVol = vol->getLogVol(); const std::string logName = logVol->getName(); - // MATERIAL - const GeoMaterial * mat = vol->getLogVol()->getMaterial(); + // MATERIAL + const GeoMaterial* mat = vol->getLogVol()->getMaterial(); - // SHAPE - const GeoShape * shape = vol->getLogVol()->getShape(); + // SHAPE + const GeoShape* shape = vol->getLogVol()->getShape(); - /* - * STORE THE OBJECTS IN THE DB - */ + /* + * STORE THE OBJECTS IN THE DB + */ - // store/get the Material object into/from the DB - unsigned int matId; - // matId = storeObj(mat, matName); - matId = storeMaterial(mat); + // store/get the Material object into/from the DB + unsigned int matId; + // matId = storeObj(mat, matName); + matId = storeMaterial(mat); - // store/get the Shape object into/from the DB - unsigned int shapeId; - shapeId = storeShape(shape); - // shapeId = storeObj(shape, shapeType, shapePars); + // store/get the Shape object into/from the DB + unsigned int shapeId; + shapeId = storeShape(shape); + // shapeId = storeObj(shape, shapeType, shapePars); - // store/get the LogVol object into/from the DB - unsigned int logvolId; - logvolId = storeObj(logVol, logName, shapeId, matId); + // store/get the LogVol object into/from the DB + unsigned int logvolId; + logvolId = storeObj(logVol, logName, shapeId, matId); - if (dynamic_cast<const GeoPhysVol*>(vol)) { - const GeoPhysVol* physVol = dynamic_cast<const GeoPhysVol*>(vol); - // store the PhysVol volume into the DB - physId = storeObj(physVol, logvolId, parentId, storeRootVolume); // with parent info + if (dynamic_cast<const GeoPhysVol*>(vol)) { + const GeoPhysVol* physVol = dynamic_cast<const GeoPhysVol*>(vol); + // store the PhysVol volume into the DB + physId = storeObj(physVol, logvolId, parentId, + storeRootVolume); // with parent info volTypeStr = "GeoPhysVol"; - } - else if (dynamic_cast<const GeoFullPhysVol*>(vol)) { - const GeoFullPhysVol* fullVol = dynamic_cast<const GeoFullPhysVol*>(vol); - physId = storeObj(fullVol, logvolId, parentId, storeRootVolume); // with parent info + } else if (dynamic_cast<const GeoFullPhysVol*>(vol)) { + const GeoFullPhysVol* fullVol = + dynamic_cast<const GeoFullPhysVol*>(vol); + physId = storeObj(fullVol, logvolId, parentId, + storeRootVolume); // with parent info volTypeStr = "GeoFullPhysVol"; - } else { - std::cout << "GeoModelWrite -- WARNING!! Unknown GeoVPhysVol type!! Exiting..." << std::endl; + } else { + std::cout << "GeoModelWrite -- WARNING!! Unknown GeoVPhysVol " + "type!! Exiting..." + << std::endl; exit(EXIT_FAILURE); - } + } - } else { - physId = getStoredIdFromAddress(address); + } else { + physId = getStoredIdFromAddress(address); volTypeStr = getGeoTypeFromVPhysVol(vol); - } + } // Now we get the 'copy number' for this volume, - // to distinguish this volume from the other volumes created from the same shared node (if any) + // to distinguish this volume from the other volumes created from the same + // shared node (if any) if (volTypeStr == "NULL") std::cout << "ERROR!! volTypeStr is 'NULL'!!!\n"; const unsigned int volCopyN = setVolumeCopyNumber(physId, volTypeStr); // debug msg - //std::cout << "WriteGeoModel -- physId: " << physId << "- volume copy number: " << volCopyN << std::endl; + if (m_loglevel >= 2) { + std::cout << "WriteGeoModel -- physId: " << physId + << "- volume copy number : " << volCopyN << std::endl; + } - if ( isRootVolume || parentId == 0) { - //qDebug() << "This is the RootVolume or the volume has 'NULL' parent (unconnected subtree?) - So, we do not store the child position for this volume!"; + if (isRootVolume || parentId == 0) { + // qDebug() << "This is the RootVolume or the volume has 'NULL' parent + // (unconnected subtree?) - So, we do not store the child position for + // this volume!"; } else { - // store the parent-child relationship in the DB - std::string parentType = getGeoTypeFromVPhysVol(parentNode); - // get the copy number of the parent - const unsigned int parentCopyN = getLatestParentCopyNumber(parentId, parentType); - std::string childType = getGeoTypeFromVPhysVol(vol); - storeChildPosition(parentId, parentType, physId, parentCopyN, getChildPosition( parentId, parentType, parentCopyN), childType, volCopyN); + // store the parent-child relationship in the DB + std::string parentType = getGeoTypeFromVPhysVol(parentNode); + // get the copy number of the parent + const unsigned int parentCopyN = + getLatestParentCopyNumber(parentId, parentType); + std::string childType = getGeoTypeFromVPhysVol(vol); + storeChildPosition(parentId, parentType, physId, parentCopyN, + getChildPosition(parentId, parentType, parentCopyN), + childType, volCopyN); } } +std::string WriteGeoModel::getGeoTypeFromVPhysVol(const GeoVPhysVol* vol) { + if (!vol) return "NULL"; - std::string WriteGeoModel::getGeoTypeFromVPhysVol(const GeoVPhysVol* vol) -{ - if (!vol) - return "NULL"; - - std::string geoType; - if (dynamic_cast<const GeoPhysVol*>(vol)) { - geoType = "GeoPhysVol"; - } - else if (dynamic_cast<const GeoFullPhysVol*>(vol)) { - geoType = "GeoFullPhysVol"; - } else { - std::cout << "GeoModelWrite -- WARNING!! Unknown GeoVPhysVol type!!" << std::endl; - } - return geoType; + std::string geoType; + if (dynamic_cast<const GeoPhysVol*>(vol)) { + geoType = "GeoPhysVol"; + } else if (dynamic_cast<const GeoFullPhysVol*>(vol)) { + geoType = "GeoFullPhysVol"; + } else { + std::cout << "GeoModelWrite -- WARNING!! Unknown GeoVPhysVol type!!" + << std::endl; + } + return geoType; } - -void WriteGeoModel::handleIdentifierTag(const GeoIdentifierTag *node) -{ - std::string address = getAddressStringFromPointer( node ); +void WriteGeoModel::handleIdentifierTag(const GeoIdentifierTag* node) { + std::string address = getAddressStringFromPointer(node); int identifier = node->getIdentifier(); - + // debug msgs - //std::cout << "WriteGeoModel::handleIdentifierTag()..." << std::endl; - //std::cout << "id: " << identifier << std::endl; - + if (m_loglevel >= 2) { + std::cout << "WriteGeoModel::handleIdentifierTag()..." << std::endl; + std::cout << "id: " << identifier << std::endl; + } + // variables used to persistify the object unsigned int itId; @@ -378,10 +405,11 @@ void WriteGeoModel::handleIdentifierTag(const GeoIdentifierTag *node) const std::vector<std::string> parentList = getParentNode(); const unsigned int parentId = std::stoi(parentList[0]); const std::string parentType = parentList[1]; - const unsigned int parentCopyN = getLatestParentCopyNumber(parentId, parentType); + const unsigned int parentCopyN = + getLatestParentCopyNumber(parentId, parentType); // check if this object has been stored already - if (! isAddressStored(address)) { + if (!isAddressStored(address)) { /* STORE THE OBJECT IN THE DB */ itId = storeObj(node, identifier); } else { @@ -389,20 +417,22 @@ void WriteGeoModel::handleIdentifierTag(const GeoIdentifierTag *node) itId = getStoredIdFromAddress(address); } - storeChildPosition(parentId, parentType, itId, parentCopyN, getChildPosition( parentId, parentType, parentCopyN ), "GeoIdentifierTag", 0); // TODO: Check if the copyN=0 at the end is OK for nodes as Transforms, which cannot be used as parents, only as children! - - + storeChildPosition( + parentId, parentType, itId, parentCopyN, + getChildPosition(parentId, parentType, parentCopyN), "GeoIdentifierTag", + 0); // TODO: Check if the copyN=0 at the end is OK for nodes as + // Transforms, which cannot be used as parents, only as children! } -void WriteGeoModel::handleSerialIdentifier(const GeoSerialIdentifier *node) -{ - std::string address = getAddressStringFromPointer( node ); +void WriteGeoModel::handleSerialIdentifier(const GeoSerialIdentifier* node) { + std::string address = getAddressStringFromPointer(node); int baseId = node->getBaseId(); - + // debug msgs - //std::cout << "WriteGeoModel::handleSerialIdentifier()..." << std::endl; - //std::cout << "baseId: " << baseId << std::endl; - + if (m_loglevel >= 2) { + std::cout << "WriteGeoModel::handleSerialIdentifier()..." << std::endl; + std::cout << "baseId: " << baseId << std::endl; + } // variables used to persistify the object unsigned int siId; @@ -410,10 +440,11 @@ void WriteGeoModel::handleSerialIdentifier(const GeoSerialIdentifier *node) const std::vector<std::string> parentList = getParentNode(); const unsigned int parentId = std::stoi(parentList[0]); const std::string parentType = parentList[1]; - const unsigned int parentCopyN = getLatestParentCopyNumber(parentId, parentType); + const unsigned int parentCopyN = + getLatestParentCopyNumber(parentId, parentType); // check if this object has been stored already - if (! isAddressStored(address)) { + if (!isAddressStored(address)) { /* STORE THE OBJECT IN THE DB */ siId = storeObj(node, baseId); } else { @@ -421,1354 +452,1752 @@ void WriteGeoModel::handleSerialIdentifier(const GeoSerialIdentifier *node) siId = getStoredIdFromAddress(address); } - storeChildPosition(parentId, parentType, siId, parentCopyN, getChildPosition( parentId, parentType, parentCopyN ), "GeoSerialIdentifier", 0); // TODO: Check if the copyN=0 at the end is OK for nodes as Transforms, which cannot be used as parents, only as children! - + storeChildPosition( + parentId, parentType, siId, parentCopyN, + getChildPosition(parentId, parentType, parentCopyN), + "GeoSerialIdentifier", + 0); // TODO: Check if the copyN=0 at the end is OK for nodes as + // Transforms, which cannot be used as parents, only as children! } +void WriteGeoModel::handleSerialDenominator(const GeoSerialDenominator* node) { + std::string address = getAddressStringFromPointer(node); + std::string baseName = node->getBaseName(); -void WriteGeoModel::handleSerialDenominator (const GeoSerialDenominator *node) -{ - std::string address = getAddressStringFromPointer( node ); - std::string baseName = node->getBaseName(); - - // variables used to persistify the object - unsigned int sdId; + // variables used to persistify the object + unsigned int sdId; - // get the parent volume - const std::vector<std::string> parentList = getParentNode(); - const unsigned int parentId = std::stoi(parentList[0]); - const std::string parentType = parentList[1]; - const unsigned int parentCopyN = getLatestParentCopyNumber(parentId, parentType); + // get the parent volume + const std::vector<std::string> parentList = getParentNode(); + const unsigned int parentId = std::stoi(parentList[0]); + const std::string parentType = parentList[1]; + const unsigned int parentCopyN = + getLatestParentCopyNumber(parentId, parentType); - // check if this object has been stored already - if (! isAddressStored(address)) { - /* STORE THE OBJECT IN THE DB */ - sdId = storeObj(node, baseName); - } else { - /* GET THE OBJECT FROM THE DB */ - sdId = getStoredIdFromAddress(address); - } + // check if this object has been stored already + if (!isAddressStored(address)) { + /* STORE THE OBJECT IN THE DB */ + sdId = storeObj(node, baseName); + } else { + /* GET THE OBJECT FROM THE DB */ + sdId = getStoredIdFromAddress(address); + } - storeChildPosition(parentId, parentType, sdId, parentCopyN, getChildPosition( parentId, parentType, parentCopyN ), "GeoSerialDenominator", 0); // TODO: Check if the copyN=0 at the end is OK for nodes as Transforms, which cannot be used as parents, only as children! + storeChildPosition( + parentId, parentType, sdId, parentCopyN, + getChildPosition(parentId, parentType, parentCopyN), + "GeoSerialDenominator", + 0); // TODO: Check if the copyN=0 at the end is OK for nodes as + // Transforms, which cannot be used as parents, only as children! } +void WriteGeoModel::handleSerialTransformer(const GeoSerialTransformer* node) { + std::string address = getAddressStringFromPointer(node); + // variables used to persistify the object + unsigned int functionId; + unsigned int physvolId; + // unsigned int physvolTable; + unsigned int nCopies; + unsigned int stId; -void WriteGeoModel::handleSerialTransformer (const GeoSerialTransformer *node) -{ - std::string address = getAddressStringFromPointer( node ); - - // variables used to persistify the object - unsigned int functionId; - unsigned int physvolId; -// unsigned int physvolTable; - unsigned int nCopies; - unsigned int stId; - - // get the parent volume - const std::vector<std::string> parentList = getParentNode(); - const unsigned int parentId = std::stoi(parentList[0]); - const std::string parentType = parentList[1]; - unsigned int parentCopyN = getLatestParentCopyNumber(parentId, parentType); - - - // check if this object has been stored already - if (! isAddressStored(address)) { - /* - * Get Node characteristics - * - * SerialTransformer features: - * - 1 parent PhysVol (if any) - * - 1 GENFUNCTION - * - 1 PhysVolId - * - 1 PhysVolType - * - 1 number of copies - */ - // get linked function and number of copies - const GeoXF::Function * func = node->getFunction(); - nCopies = node->getNCopies(); - - // get linked VPhysVol volume - const GeoVPhysVol *vol = &( *( node->getVolume() ) ); - // const GeoPhysVol* vol = dynamic_cast<const GeoPhysVol*>(volV); - std::string volType; - if (dynamic_cast<const GeoPhysVol*>(vol)) { - volType = "GeoPhysVol"; - } else if (dynamic_cast<const GeoFullPhysVol*>(vol)) { - volType = "GeoFullPhysVol"; - } else { - std::cout << "ERROR!!! Unknown VPhysVol type!!" << std::endl; - } - - /* - * Persistify the Function - */ - TransFunctionPersistifier persistifier; + // get the parent volume + const std::vector<std::string> parentList = getParentNode(); + const unsigned int parentId = std::stoi(parentList[0]); + const std::string parentType = parentList[1]; + unsigned int parentCopyN = getLatestParentCopyNumber(parentId, parentType); + + // check if this object has been stored already + if (!isAddressStored(address)) { + /* + * Get Node characteristics + * + * SerialTransformer features: + * - 1 parent PhysVol (if any) + * - 1 GENFUNCTION + * - 1 PhysVolId + * - 1 PhysVolType + * - 1 number of copies + */ + // get linked function and number of copies + const GeoXF::Function* func = node->getFunction(); + nCopies = node->getNCopies(); + + // get linked VPhysVol volume + const GeoVPhysVol* vol = &(*(node->getVolume())); + // const GeoPhysVol* vol = dynamic_cast<const GeoPhysVol*>(volV); + std::string volType; + if (dynamic_cast<const GeoPhysVol*>(vol)) { + volType = "GeoPhysVol"; + } else if (dynamic_cast<const GeoFullPhysVol*>(vol)) { + volType = "GeoFullPhysVol"; + } else { + std::cout << "ERROR!!! Unknown VPhysVol type!!" << std::endl; + } + + /* + * Persistify the Function + */ + TransFunctionPersistifier persistifier; try { persistifier.persistify(*func); - } catch (const std::runtime_error & error) { - std::cout << "GeoModelWrite -- SEVERE WARNING!! Handling std::runtime_error! -->" << error.what() << std::endl; + } catch (const std::runtime_error& error) { + std::cout << "GeoModelWrite -- SEVERE WARNING!! Handling " + "std::runtime_error! -->" + << error.what() << std::endl; } - std::string expression = persistifier.getCodedString(); - - if (expression.size() == 0) { - std::cout << "FATAL ERROR!! Function expression is empty!! Aborting...\n"; - exit(EXIT_FAILURE); - } - - - /* - * STORE/GET THE INNER OBJECTS IN THE DB - */ - - // store/get the Function object in the DB - functionId = storeObj(func, expression); - - // store/get the PhysVol volume in the DB - - /* Concerning the physVol referenced by the SerialTransformer: - * - * - if physvol is not stored in the DB already; - * - if physVol has no parent (==NULL) - * ==> it means that its children will never visited by the NodeAction executed on the root tree - * - * ==> So, we need to persitify it as a new tree, to get all its children visited and persistified - * - */ - handleReferencedVPhysVol(vol); - - std::string physvolAddress = getAddressStringFromPointer(vol); - physvolId = getStoredIdFromAddress(physvolAddress); + std::string expression = persistifier.getCodedString(); + if (expression.size() == 0) { + std::cout + << "FATAL ERROR!! Function expression is empty!! Aborting...\n"; + exit(EXIT_FAILURE); + } - /* - * STORE THE NODE INTO THE DB AND ITS POSITION WITHIN THE TREE - */ - // store the SerialTransformer volume in the DB - stId = storeObj(node, functionId, physvolId, volType, nCopies); - } - else { - stId = getStoredIdFromAddress(address); - } + /* + * STORE/GET THE INNER OBJECTS IN THE DB + */ + + // store/get the Function object in the DB + functionId = storeObj(func, expression); + + // store/get the PhysVol volume in the DB + + /* Concerning the physVol referenced by the SerialTransformer: + * + * - if physvol is not stored in the DB already; + * - if physVol has no parent (==NULL) + * ==> it means that its children will never visited by the NodeAction + * executed on the root tree + * + * ==> So, we need to persitify it as a new tree, to get all its + * children visited and persistified + * + */ + handleReferencedVPhysVol(vol); + + std::string physvolAddress = getAddressStringFromPointer(vol); + physvolId = getStoredIdFromAddress(physvolAddress); + + /* + * STORE THE NODE INTO THE DB AND ITS POSITION WITHIN THE TREE + */ + // store the SerialTransformer volume in the DB + stId = storeObj(node, functionId, physvolId, volType, nCopies); + } else { + stId = getStoredIdFromAddress(address); + } - storeChildPosition(parentId, parentType, stId, parentCopyN, getChildPosition( parentId, parentType, parentCopyN ), "GeoSerialTransformer", 0); // TODO: Check if the copyN=0 at the end is OK for nodes as Transforms, which cannot be used as parents, only as children! + storeChildPosition( + parentId, parentType, stId, parentCopyN, + getChildPosition(parentId, parentType, parentCopyN), + "GeoSerialTransformer", + 0); // TODO: Check if the copyN=0 at the end is OK for nodes as + // Transforms, which cannot be used as parents, only as children! } +void WriteGeoModel::handleTransform(const GeoTransform* node) { + std::string address = getAddressStringFromPointer(node); + // get the parent volume + const std::vector<std::string> parentList = getParentNode(); + const unsigned int parentId = std::stoi(parentList[0]); + const std::string parentType = parentList[1]; + unsigned int parentCopyN = getLatestParentCopyNumber(parentId, parentType); -void WriteGeoModel::handleTransform(const GeoTransform* node) -{ - std::string address = getAddressStringFromPointer( node ); - - // get the parent volume - const std::vector<std::string> parentList = getParentNode(); - const unsigned int parentId = std::stoi(parentList[0]); - const std::string parentType = parentList[1]; - - unsigned int parentCopyN = getLatestParentCopyNumber(parentId, parentType); - - /* - * STORE THE OBJECT IN THE DB AND ITS PLACE WITHIN THE TREE - */ - - // store the transformation in the DB - unsigned int trId = storeTranform(node); - - // Store the child-parent relationship - - if ( dynamic_cast<const GeoAlignableTransform*>(node) ) { - storeChildPosition(parentId, parentType, trId, parentCopyN, getChildPosition( parentId, parentType, parentCopyN ), "GeoAlignableTransform", 0); // TODO: Check if the copyN=0 at the end is OK for nodes as Transforms, which cannot be used as parents, only as children! - } - else if ( dynamic_cast<const GeoTransform*>(node) ) { - storeChildPosition(parentId, parentType, trId, parentCopyN, getChildPosition( parentId, parentType, parentCopyN ), "GeoTransform", 0); // TODO: Check if the copyN=0 at the end is OK for nodes as Transforms, which cannot be used as parents, only as children! - } - else { - std::cout << "ERROR!! Unknwon Transform type! Exiting..." << std::endl; - exit(EXIT_FAILURE); - } - + /* + * STORE THE OBJECT IN THE DB AND ITS PLACE WITHIN THE TREE + */ + + // store the transformation in the DB + unsigned int trId = storeTranform(node); + + // Store the child-parent relationship + + if (dynamic_cast<const GeoAlignableTransform*>(node)) { + storeChildPosition(parentId, parentType, trId, parentCopyN, + getChildPosition(parentId, parentType, parentCopyN), + "GeoAlignableTransform", + 0); // TODO: Check if the copyN=0 at the end is OK + // for nodes as Transforms, which cannot be used + // as parents, only as children! + } else if (dynamic_cast<const GeoTransform*>(node)) { + storeChildPosition(parentId, parentType, trId, parentCopyN, + getChildPosition(parentId, parentType, parentCopyN), + "GeoTransform", + 0); // TODO: Check if the copyN=0 at the end is OK + // for nodes as Transforms, which cannot be used + // as parents, only as children! + } else { + std::cout << "ERROR!! Unknwon Transform type! Exiting..." << std::endl; + exit(EXIT_FAILURE); + } } +void WriteGeoModel::handleNameTag(const GeoNameTag* node) { + std::string name = node->getName(); + const std::string address = getAddressStringFromPointer(node); + // get the parent volume + const std::vector<std::string> parentList = getParentNode(); + const unsigned int parentId = std::stoi(parentList[0]); + const std::string parentType = parentList[1]; + unsigned int parentCopyN = getLatestParentCopyNumber(parentId, parentType); -void WriteGeoModel::handleNameTag(const GeoNameTag* node) -{ - std::string name = node->getName(); - const std::string address = getAddressStringFromPointer( node ); - // get the parent volume - const std::vector<std::string> parentList = getParentNode(); - const unsigned int parentId = std::stoi(parentList[0]); - const std::string parentType = parentList[1]; - unsigned int parentCopyN = getLatestParentCopyNumber(parentId, parentType); - - // FIXME: TODO: add "if stored"... + // FIXME: TODO: add "if stored"... - /* - * STORE THE OBJECT IN THE DB AND ITS POSITION WITHIN THE TREE - */ + /* + * STORE THE OBJECT IN THE DB AND ITS POSITION WITHIN THE TREE + */ - // store the name tag in the DB - unsigned int nameId = storeObj(node, name); + // store the name tag in the DB + unsigned int nameId = storeObj(node, name); - // Store the child-parent relationship - storeChildPosition(parentId, parentType, nameId, parentCopyN, getChildPosition( parentId, parentType, parentCopyN ), "GeoNameTag", 0); + // Store the child-parent relationship + storeChildPosition(parentId, parentType, nameId, parentCopyN, + getChildPosition(parentId, parentType, parentCopyN), + "GeoNameTag", 0); } - - //__________________________________________________ - std::vector<std::string> WriteGeoModel::getParentNode() -{ - // check the current volume position in the geometry tree - GeoNodePath* path = getPath(); - unsigned int len = path->getLength(); - - // reset the number of visited node, if len is different than before - if (len > m_len) { - m_len_nChild = 0; - m_len = len; - } - // update number of visited nodes if len is the same as before - else { - ++m_len_nChild; - } - - // get the parent volume, if this is not the Root volume - const GeoVPhysVol* parentNode = nullptr; - unsigned int parentId = 0; - std::string parentType = "NULL"; - - if (len >= 1) - { - // get the parent node - parentNode = path->getItem(len-1); // i=(len-1) gives you the parent VPhysVol - - if (parentNode) { - - // get the parent type - parentType = getGeoTypeFromVPhysVol(parentNode); - - // get the parent memory address - std::string parentAddress = getAddressStringFromPointer(parentNode); +std::vector<std::string> WriteGeoModel::getParentNode() { + // check the current volume position in the geometry tree + GeoNodePath* path = getPath(); + unsigned int len = path->getLength(); + + // reset the number of visited node, if len is different than before + if (len > m_len) { + m_len_nChild = 0; + m_len = len; + } + // update number of visited nodes if len is the same as before + else { + ++m_len_nChild; + } - // get the id of the parent node, which should be stored already in the DB - if (isAddressStored(parentAddress)) { - parentId = getStoredIdFromAddress(parentAddress); - } - else { - std::cout << "The parent node of this child node seems to not having be stored in the DB yet! [It is normal if it is the root volume or a transformation node used for example only in the definition of a 'GeoShapeShift' instance]" << std::endl; - } - } - } - else{ - std::cout << "GeoModelWrite -- WARNING!! Len == 0, but this cannot be the Root volume!" << std::endl; - } + // get the parent volume, if this is not the Root volume + const GeoVPhysVol* parentNode = nullptr; + unsigned int parentId = 0; + std::string parentType = "NULL"; + + if (len >= 1) { + // get the parent node + parentNode = + path->getItem(len - 1); // i=(len-1) gives you the parent VPhysVol + + if (parentNode) { + // get the parent type + parentType = getGeoTypeFromVPhysVol(parentNode); + + // get the parent memory address + std::string parentAddress = getAddressStringFromPointer(parentNode); + + // get the id of the parent node, which should be stored already in + // the DB + if (isAddressStored(parentAddress)) { + parentId = getStoredIdFromAddress(parentAddress); + } else { + std::cout + << "The parent node of this child node seems to not having " + "be stored in the DB yet! [It is normal if it is the " + "root volume or a transformation node used for example " + "only in the definition of a 'GeoShapeShift' instance]" + << std::endl; + } + } + } else { + std::cout << "GeoModelWrite -- WARNING!! Len == 0, but this cannot be " + "the Root volume!" + << std::endl; + } - std::vector<std::string> parentList; - parentList.insert(parentList.begin(), {std::to_string(parentId), parentType}); //INT + std::vector<std::string> parentList; + parentList.insert(parentList.begin(), + {std::to_string(parentId), parentType}); // INT - return parentList; + return parentList; } - //__________________________________________________________________ -unsigned int WriteGeoModel::storeShape(const GeoShape* shape) -{ -// QString shapeType = QString::fromStdString(shape->type()); - std::string shapeType = shape->type(); - - // LArCustomShape is deprecated. Write it out as a GeoUnidentifiedShape; - if (shapeType=="CustomShape") shapeType="UnidentifiedShape"; - - // get shape parameters - std::string shapePars = getShapeParameters(shape); - - // store the shape in the DB and returns the ID - return storeObj(shape, shapeType, shapePars); -} +unsigned int WriteGeoModel::storeShape(const GeoShape* shape) { + // QString shapeType = QString::fromStdString(shape->type()); + std::string shapeType = shape->type(); + // LArCustomShape is deprecated. Write it out as a GeoUnidentifiedShape; + if (shapeType == "CustomShape") shapeType = "UnidentifiedShape"; + + // get shape parameters + std::string shapePars = getShapeParameters(shape); + + // store the shape in the DB and returns the ID + return storeObj(shape, shapeType, shapePars); +} //______________________________________________________________________ -unsigned int WriteGeoModel::storeMaterial(const GeoMaterial* mat) -{ - const std::string matName = mat->getName(); //The name of the material. - const double matDensity = mat->getDensity(); //The density of the material. - const unsigned int numElements = mat->getNumElements(); +unsigned int WriteGeoModel::storeMaterial(const GeoMaterial* mat) { + const std::string matName = mat->getName(); // The name of the material. + const double matDensity = mat->getDensity(); // The density of the + // material. + const unsigned int numElements = mat->getNumElements(); + + // loop over the elements composing the material + std::string matElements; + std::vector<std::string> matElementsList; + for (unsigned int i = 0; i < numElements; i++) { + // Gets the i-th element. + const GeoElement* element = mat->getElement(i); + std::string elName = element->getName(); + + // Store the element and get its DataBase ID + unsigned int elementId = storeElement(element); + + // Gets the fraction by weight of the i-th element + const std::string elementFraction = + to_string_with_precision(mat->getFraction(i)); + + matElementsList.push_back(std::to_string(elementId) + ":" + + elementFraction); // INT+string + } + matElements = joinVectorStrings(matElementsList, ";"); - // loop over the elements composing the material - std::string matElements; - std::vector<std::string> matElementsList; - for (unsigned int i=0; i < numElements; i++) { + // store the material in the DB and returns the ID + return storeObj(mat, matName, matDensity, matElements); +} - //Gets the i-th element. - const GeoElement* element = mat->getElement(i); - std::string elName = element->getName(); +//_______________________________________________________________________ +unsigned int WriteGeoModel::storeElement(const GeoElement* el) { + // The name of the element, e.g. "Carbon". + const std::string elName = el->getName(); - // Store the element and get its DataBase ID - unsigned int elementId = storeElement(element); + // The chemical symbol for the element, e.g. C, O, S, Na.... + const std::string elSymbol = el->getSymbol(); - //Gets the fraction by weight of the i-th element - const std::string elementFraction = to_string_with_precision( mat->getFraction(i) ); + // The atomic number Z for the material. + const double elZ = el->getZ(); - matElementsList.push_back( std::to_string(elementId) + ":" + elementFraction ); //INT+string - } - matElements = joinVectorStrings(matElementsList, ";"); + // The average atomic mass for the element. + const double elA = el->getA(); - // store the material in the DB and returns the ID - return storeObj(mat, matName, matDensity, matElements); + // store the material in the DB and returns the ID + return storeObj(el, elName, elSymbol, elZ, elA); } - //_______________________________________________________________________ -unsigned int WriteGeoModel::storeElement(const GeoElement* el) -{ - // The name of the element, e.g. "Carbon". - const std::string elName = el->getName(); +unsigned int WriteGeoModel::storeTranform(const GeoTransform* node) { + /* + * STORE THE OBJECT IN THE DB + */ - // The chemical symbol for the element, e.g. C, O, S, Na.... - const std::string elSymbol = el->getSymbol(); + std::string address = getAddressStringFromPointer(node); - // The atomic number Z for the material. - const double elZ = el->getZ(); + unsigned int trId = 0; - // The average atomic mass for the element. - const double elA = el->getA(); + // check if this object has been stored already + if (!isAddressStored(address)) { + // TODO: simplify and put common code in a separate class + + /* + * get the 12 matrix elements + */ + // Get the 9 rotation coefficients + // NOTE: we use the 'getDefTransform' method, + // instead of the 'getTransform' one, + // because we want to get the 'default position' + // for GeoAlignableTransforms. + // For GeoAlignableTransform, in fact, + // the 'getTransform' method returns the transformation plus + // the alignment constants. + // Both methods return the same transform for GeoTransforms. + double xx = node->getDefTransform()(0, 0); + double xy = node->getDefTransform()(0, 1); + double xz = node->getDefTransform()(0, 2); + + double yx = node->getDefTransform()(1, 0); + double yy = node->getDefTransform()(1, 1); + double yz = node->getDefTransform()(1, 2); + + double zx = node->getDefTransform()(2, 0); + double zy = node->getDefTransform()(2, 1); + double zz = node->getDefTransform()(2, 2); + + // Get the 3 translation coefficients + double dx = node->getDefTransform()(0, 3); + double dy = node->getDefTransform()(1, 3); + double dz = node->getDefTransform()(2, 3); + + // Instanciate an Eigen's 3D Transformation + GeoTrf::Transform3D tr; + + // set rotation + tr(0, 0) = xx; + tr(0, 1) = xy; + tr(0, 2) = xz; + + tr(1, 0) = yx; + tr(1, 1) = yy; + tr(1, 2) = yz; + + tr(2, 0) = zx; + tr(2, 1) = zy; + tr(2, 2) = zz; + + // set translation vector/column + tr(0, 3) = dx; + tr(1, 3) = dy; + tr(2, 3) = dz; + + // explicitely set the last row: (0,0,0,1) + tr(3, 0) = 0; + tr(3, 1) = 0; + tr(3, 2) = 0; + tr(3, 3) = 1; + + std::vector<double> params = getTransformParameters(tr); + + /* + * STORE THE OBJECT IN THE DB + */ + + // store the object in the DB + if (dynamic_cast<const GeoAlignableTransform*>(node)) { + trId = storeObj(dynamic_cast<const GeoAlignableTransform*>(node), + params); + } else if (dynamic_cast<const GeoTransform*>(node)) { + trId = storeObj(dynamic_cast<const GeoTransform*>(node), params); + } else { + std::cout << "ERROR!!! - Unknown type of transformation! Exiting..." + << std::endl; + exit(EXIT_FAILURE); + } + } else { + trId = getStoredIdFromAddress(address); + } - // store the material in the DB and returns the ID - return storeObj(el, elName, elSymbol, elZ, elA); + if (!trId) { + std::cout + << "ERROR!!! - Error while handling a Transform node! Exiting..." + << std::endl; + exit(EXIT_FAILURE); + } + return trId; } - //_______________________________________________________________________ -unsigned int WriteGeoModel::storeTranform(const GeoTransform* node) -{ - /* - * STORE THE OBJECT IN THE DB - */ - - std::string address = getAddressStringFromPointer( node ); - - unsigned int trId = 0; - - // check if this object has been stored already - if (! isAddressStored(address)) { - - // TODO: simplify and put common code in a separate class - - /* - * get the 12 matrix elements - */ - // Get the 9 rotation coefficients - double xx = node->getTransform()(0, 0); - double xy = node->getTransform()(0, 1); - double xz = node->getTransform()(0, 2); - - double yx = node->getTransform()(1, 0); - double yy = node->getTransform()(1, 1); - double yz = node->getTransform()(1, 2); - - double zx = node->getTransform()(2, 0); - double zy = node->getTransform()(2, 1); - double zz = node->getTransform()(2, 2); - - // Get the 3 translation coefficients - double dx = node->getTransform()(0, 3); - double dy = node->getTransform()(1, 3); - double dz = node->getTransform()(2, 3); - - - // Instanciate an Eigen's 3D Transformation - GeoTrf::Transform3D tr; - - // set rotation - tr(0,0)=xx; - tr(0,1)=xy; - tr(0,2)=xz; - - tr(1,0)=yx; - tr(1,1)=yy; - tr(1,2)=yz; - - tr(2,0)=zx; - tr(2,1)=zy; - tr(2,2)=zz; - - // set translation vector/column - tr(0,3)=dx; - tr(1,3)=dy; - tr(2,3)=dz; - - // explicitely set the last row: (0,0,0,1) - tr(3,0)=0; - tr(3,1)=0; - tr(3,2)=0; - tr(3,3)=1; - - std::vector<double> params = getTransformParameters(tr); - - /* - * STORE THE OBJECT IN THE DB - */ - - // store the object in the DB - if ( dynamic_cast<const GeoAlignableTransform*>(node) ) { - trId = storeObj(dynamic_cast<const GeoAlignableTransform*>(node), params); - } - else if ( dynamic_cast<const GeoTransform*>(node) ) { - trId = storeObj(dynamic_cast<const GeoTransform*>(node), params); - } - else { - std::cout << "ERROR!!! - Unknown type of transformation! Exiting..." << std::endl; - exit(EXIT_FAILURE); - } - } else { - trId = getStoredIdFromAddress(address); - } - - if(!trId) { - std::cout << "ERROR!!! - Error while handling a Transform node! Exiting..." << std::endl; - exit(EXIT_FAILURE); - } - return trId; -} - +void WriteGeoModel::handleReferencedVPhysVol(const GeoVPhysVol* vol) { + // qDebug() << "PhysVol's LogVol name:" << + // QString::fromStdString(vol->getLogVol()->getName()); -//_______________________________________________________________________ -void WriteGeoModel::handleReferencedVPhysVol (const GeoVPhysVol *vol) -{ - // qDebug() << "PhysVol's LogVol name:" << QString::fromStdString(vol->getLogVol()->getName()); + // get the address string for the current volume + std::string address = getAddressStringFromPointer(vol); - // get the address string for the current volume - std::string address = getAddressStringFromPointer( vol ); + unsigned int parentId = 0; - unsigned int parentId = 0; + m_unconnectedTree = false; - m_unconnectedTree = false; + // get the parent volume, if this is not the Root volume + // JFB The following construct does not work: what if the parent is null? + // const GeoVPhysVol* parentNode = dynamic_cast<const GeoVPhysVol*>( + // &(*(vol->getParent() ))); + /// JFB So I replaced it by the next two lines: + auto p = vol->getParent(); + const GeoVPhysVol* parentNode = + p ? dynamic_cast<const GeoVPhysVol*>(&(*(vol->getParent()))) : nullptr; - // get the parent volume, if this is not the Root volume - // JFB The following construct does not work: what if the parent is null? - // const GeoVPhysVol* parentNode = dynamic_cast<const GeoVPhysVol*>( &(*(vol->getParent() ))); - /// JFB So I replaced it by the next two lines: - auto p=vol->getParent(); - const GeoVPhysVol* parentNode = p ? dynamic_cast<const GeoVPhysVol*>( &(*(vol->getParent() ))) : nullptr; - - if (parentNode) { - std::string parentAddress = getAddressStringFromPointer(parentNode); + if (parentNode) { + std::string parentAddress = getAddressStringFromPointer(parentNode); - if (isAddressStored(parentAddress)) - parentId = getStoredIdFromAddress(parentAddress); - // else - // qFatal("FATAL ERROR!!! - The parent node of this child should has been stored in the DB already, but it was not found!!"); + if (isAddressStored(parentAddress)) + parentId = getStoredIdFromAddress(parentAddress); + // else + // qFatal("FATAL ERROR!!! - The parent node of this + // child should has been stored in the DB already, but it was not + // found!!"); - //qDebug() << "--> parent's LogVol name:" << QString::fromStdString(parentNode->getLogVol()->getName()); - } - else { - //qDebug() << "NULL parent node!! --> it seems to be an unconnected subtree."; - //qDebug() << "setting 'unconnected' to: true"; - m_unconnectedTree = true; - } + // qDebug() << "--> parent's LogVol name:" << + // QString::fromStdString(parentNode->getLogVol()->getName()); + } else { + // qDebug() << "NULL parent node!! --> it seems to be an unconnected + // subtree."; qDebug() << "setting 'unconnected' to: true"; + m_unconnectedTree = true; + } - // for Debug - // // counting children - // unsigned int nChildren = vol->getNChildVols(); - // qDebug() << "number of child physical volumes:" << nChildren; - // qDebug() << "[number of PhysVol and SerialTransformer child nodes:" << vol->getNChildVolAndST() << "]"; - // - // GeoCountVolAction cv; - // cv.setDepthLimit(1); - // vol->exec(&cv); - // int nChildCount = cv.getCount(); - // qDebug() << "number of child volumes:" << nChildCount; + // for Debug + // // counting children + // unsigned int nChildren = vol->getNChildVols(); + // qDebug() << "number of child physical volumes:" << nChildren; + // qDebug() << "[number of PhysVol and SerialTransformer child nodes:" << + // vol->getNChildVolAndST() << "]"; + // + // GeoCountVolAction cv; + // cv.setDepthLimit(1); + // vol->exec(&cv); + // int nChildCount = cv.getCount(); + // qDebug() << "number of child volumes:" << nChildCount; + // check if this object has been stored already + if (!isAddressStored(address)) { + // qDebug() << "This is a new root PhysVol node of an 'unconnected' + // tree, so we start another action on it to dump it into the DB..."; + // Dump the tree volumes into the DB + vol->exec(this); // TODO: check if the new action overwrites the id of + // the volumes already in the DB...!!! - // check if this object has been stored already - if (! isAddressStored(address)) { + } else { + // qDebug() << "The referenced volume has been stored already. + // Skipping..."; + } + // at the end, we make sure we reset the status + // qDebug() << "setting 'unconnected' to: false"; + m_unconnectedTree = false; +} - //qDebug() << "This is a new root PhysVol node of an 'unconnected' tree, so we start another action on it to dump it into the DB..."; +// Get shape parameters +std::string WriteGeoModel::getShapeParameters(const GeoShape* shape) { + const std::string shapeType = shape->type(); + + std::string shapePars = ""; + std::vector<std::string> pars; + + if (shapeType == "Box") { + const GeoBox* box = dynamic_cast<const GeoBox*>(shape); + pars.push_back("XHalfLength=" + + to_string_with_precision(box->getXHalfLength())); + pars.push_back("YHalfLength=" + + to_string_with_precision(box->getYHalfLength())); + pars.push_back("ZHalfLength=" + + to_string_with_precision(box->getZHalfLength())); + shapePars = joinVectorStrings(pars, ";"); + } else if (shapeType == "Cons") { + const GeoCons* shapeIn = dynamic_cast<const GeoCons*>(shape); + pars.push_back("RMin1=" + + to_string_with_precision(shapeIn->getRMin1())); + pars.push_back("RMin2=" + + to_string_with_precision(shapeIn->getRMin2())); + pars.push_back("RMax1=" + + to_string_with_precision(shapeIn->getRMax1())); + pars.push_back("RMax2=" + + to_string_with_precision(shapeIn->getRMax2())); + pars.push_back("DZ=" + to_string_with_precision(shapeIn->getDZ())); + pars.push_back("SPhi=" + to_string_with_precision(shapeIn->getSPhi())); + pars.push_back("DPhi=" + to_string_with_precision(shapeIn->getDPhi())); + } else if (shapeType == "Torus") { + // Member Data: + // * Rmax - outside radius of the torus tube + // * Rmin - inside radius of the torus tube (Rmin=0 if not hollow) + // * Rtor - radius of the torus itself + // * + // * SPhi - starting angle of the segment in radians + // * DPhi - delta angle of the segment in radians + // + const GeoTorus* shapeIn = dynamic_cast<const GeoTorus*>(shape); + pars.push_back("Rmin=" + to_string_with_precision(shapeIn->getRMin())); + pars.push_back("Rmax=" + to_string_with_precision(shapeIn->getRMax())); + pars.push_back("Rtor=" + to_string_with_precision(shapeIn->getRTor())); + pars.push_back("SPhi=" + to_string_with_precision(shapeIn->getSPhi())); + pars.push_back("DPhi=" + to_string_with_precision(shapeIn->getDPhi())); + } else if (shapeType == "Para") { + const GeoPara* shapeIn = dynamic_cast<const GeoPara*>(shape); + pars.push_back("XHalfLength=" + + to_string_with_precision(shapeIn->getXHalfLength())); + pars.push_back("YHalfLength=" + + to_string_with_precision(shapeIn->getYHalfLength())); + pars.push_back("ZHalfLength=" + + to_string_with_precision(shapeIn->getZHalfLength())); + pars.push_back("Alpha=" + + to_string_with_precision(shapeIn->getAlpha())); + pars.push_back("Theta=" + + to_string_with_precision(shapeIn->getTheta())); + pars.push_back("Phi=" + to_string_with_precision(shapeIn->getPhi())); + } else if (shapeType == "Pcon") { + const GeoPcon* shapeIn = dynamic_cast<const GeoPcon*>(shape); + pars.push_back("SPhi=" + to_string_with_precision(shapeIn->getSPhi())); + pars.push_back("DPhi=" + to_string_with_precision(shapeIn->getDPhi())); + // get number of Z planes and loop over them + const int nZplanes = shapeIn->getNPlanes(); + pars.push_back("NZPlanes=" + std::to_string(nZplanes)); // INT + for (int i = 0; i < nZplanes; ++i) { + pars.push_back("ZPos=" + + to_string_with_precision(shapeIn->getZPlane(i))); + pars.push_back("ZRmin=" + + to_string_with_precision(shapeIn->getRMinPlane(i))); + pars.push_back("ZRmax=" + + to_string_with_precision(shapeIn->getRMaxPlane(i))); + } + } else if (shapeType == "Pgon") { + const GeoPgon* shapeIn = dynamic_cast<const GeoPgon*>(shape); + pars.push_back("SPhi=" + to_string_with_precision(shapeIn->getSPhi())); + pars.push_back("DPhi=" + to_string_with_precision(shapeIn->getDPhi())); + pars.push_back("NSides=" + + std::to_string(shapeIn->getNSides())); // INT + // get number of Z planes and loop over them + const int nZplanes = shapeIn->getNPlanes(); + pars.push_back("NZPlanes=" + std::to_string(nZplanes)); // INT + for (int i = 0; i < nZplanes; ++i) { + pars.push_back("ZPos=" + + to_string_with_precision(shapeIn->getZPlane(i))); + pars.push_back("ZRmin=" + + to_string_with_precision(shapeIn->getRMinPlane(i))); + pars.push_back("ZRmax=" + + to_string_with_precision(shapeIn->getRMaxPlane(i))); + } + } else if (shapeType == "SimplePolygonBrep") { + const GeoSimplePolygonBrep* shapeIn = + dynamic_cast<const GeoSimplePolygonBrep*>(shape); + pars.push_back("DZ=" + to_string_with_precision(shapeIn->getDZ())); + // get number of vertices and loop over them + const int nVertices = shapeIn->getNVertices(); + pars.push_back("NVertices=" + std::to_string(nVertices)); // INT + for (int i = 0; i < nVertices; ++i) { + pars.push_back("xV=" + + to_string_with_precision(shapeIn->getXVertex(i))); + pars.push_back("yV=" + + to_string_with_precision(shapeIn->getYVertex(i))); + } + } else if (shapeType == "Trap") { + const GeoTrap* shapeIn = dynamic_cast<const GeoTrap*>(shape); + pars.push_back("ZHalfLength=" + + to_string_with_precision(shapeIn->getZHalfLength())); + pars.push_back("Theta=" + + to_string_with_precision(shapeIn->getTheta())); + pars.push_back("Phi=" + to_string_with_precision(shapeIn->getPhi())); + pars.push_back("Dydzn=" + + to_string_with_precision(shapeIn->getDydzn())); + pars.push_back("Dxdyndzn=" + + to_string_with_precision(shapeIn->getDxdyndzn())); + pars.push_back("Dxdypdzn=" + + to_string_with_precision(shapeIn->getDxdypdzn())); + pars.push_back("Angleydzn=" + + to_string_with_precision(shapeIn->getAngleydzn())); + pars.push_back("Dydzp=" + + to_string_with_precision(shapeIn->getDydzp())); + pars.push_back("Dxdyndzp=" + + to_string_with_precision(shapeIn->getDxdyndzp())); + pars.push_back("Dxdypdzp=" + + to_string_with_precision(shapeIn->getDxdypdzp())); + pars.push_back("Angleydzp=" + + to_string_with_precision(shapeIn->getAngleydzp())); + } else if (shapeType == "TwistedTrap") { + const GeoTwistedTrap* shapeIn = + dynamic_cast<const GeoTwistedTrap*>(shape); + pars.push_back("PhiTwist=" + + to_string_with_precision(shapeIn->getPhiTwist())); + pars.push_back("ZHalfLength=" + + to_string_with_precision(shapeIn->getZHalfLength())); + pars.push_back("Theta=" + + to_string_with_precision(shapeIn->getTheta())); + pars.push_back("Phi=" + to_string_with_precision(shapeIn->getPhi())); + pars.push_back("DY1HalfLength=" + + to_string_with_precision(shapeIn->getY1HalfLength())); + pars.push_back("DX1HalfLength=" + + to_string_with_precision(shapeIn->getX1HalfLength())); + pars.push_back("DX2HalfLength=" + + to_string_with_precision(shapeIn->getX2HalfLength())); + pars.push_back("DY2HalfLength=" + + to_string_with_precision(shapeIn->getY2HalfLength())); + pars.push_back("DX3HalfLength=" + + to_string_with_precision(shapeIn->getX3HalfLength())); + pars.push_back("DX4HalfLength=" + + to_string_with_precision(shapeIn->getX4HalfLength())); + pars.push_back("DTiltAngleAlpha=" + + to_string_with_precision(shapeIn->getTiltAngleAlpha())); + + } else if (shapeType == "Trd") { + const GeoTrd* shapeIn = dynamic_cast<const GeoTrd*>(shape); + pars.push_back("XHalfLength1=" + + to_string_with_precision(shapeIn->getXHalfLength1())); + pars.push_back("XHalfLength2=" + + to_string_with_precision(shapeIn->getXHalfLength2())); + pars.push_back("YHalfLength1=" + + to_string_with_precision(shapeIn->getYHalfLength1())); + pars.push_back("YHalfLength2=" + + to_string_with_precision(shapeIn->getYHalfLength2())); + pars.push_back("ZHalfLength=" + + to_string_with_precision(shapeIn->getZHalfLength())); + } else if (shapeType == "Tube") { + const GeoTube* tube = dynamic_cast<const GeoTube*>(shape); + pars.push_back("RMin=" + to_string_with_precision(tube->getRMin())); + pars.push_back("RMax=" + to_string_with_precision(tube->getRMax())); + pars.push_back("ZHalfLength=" + + to_string_with_precision(tube->getZHalfLength())); + } else if (shapeType == "Tubs") { + const GeoTubs* shapeIn = dynamic_cast<const GeoTubs*>(shape); + pars.push_back("RMin=" + to_string_with_precision(shapeIn->getRMin())); + pars.push_back("RMax=" + to_string_with_precision(shapeIn->getRMax())); + pars.push_back("ZHalfLength=" + + to_string_with_precision(shapeIn->getZHalfLength())); + pars.push_back("SPhi=" + to_string_with_precision(shapeIn->getSPhi())); + pars.push_back("DPhi=" + to_string_with_precision(shapeIn->getDPhi())); + } else if (shapeType == "TessellatedSolid") { + const GeoTessellatedSolid* shapeIn = + dynamic_cast<const GeoTessellatedSolid*>(shape); + // get number of facets + const size_t nFacets = shapeIn->getNumberOfFacets(); + pars.push_back("nFacets=" + std::to_string(nFacets)); // size_t + // loop over the facets + for (size_t i = 0; i < nFacets; ++i) { + GeoFacet* facet = shapeIn->getFacet(i); + // get GeoFacet actual implementation + if (dynamic_cast<GeoTriangularFacet*>(facet)) + pars.push_back("TRI"); + else if (dynamic_cast<GeoQuadrangularFacet*>(facet)) + pars.push_back("QUAD"); + // get vertex type (ABSOLUTE/RELATIVE) + GeoFacet::GeoFacetVertexType facetVertexType = + facet->getVertexType(); + if (facetVertexType == GeoFacet::ABSOLUTE) + pars.push_back("vT=ABSOLUTE"); + if (facetVertexType == GeoFacet::RELATIVE) + pars.push_back("vT=RELATIVE"); + // get number of vertices and loop over them + const size_t nVertices = facet->getNumberOfVertices(); + pars.push_back("nV=" + std::to_string(nVertices)); // size_t + for (size_t i = 0; i < nVertices; ++i) { + GeoFacetVertex facetVertex = facet->getVertex(i); + pars.push_back("xV=" + + to_string_with_precision(facetVertex[0])); + pars.push_back("yV=" + + to_string_with_precision(facetVertex[1])); + pars.push_back("zV=" + + to_string_with_precision(facetVertex[2])); + } + } + } else if (shapeType == "Intersection") { + const GeoShapeIntersection* shapeIn = + dynamic_cast<const GeoShapeIntersection*>(shape); + // get the referenced Shape used in the 'union' operation, store it in + // the DB + const GeoShape* shapeOpA = shapeIn->getOpA(); + const unsigned int shapeIdA = storeShape(shapeOpA); + const GeoShape* shapeOpB = shapeIn->getOpB(); + const unsigned int shapeIdB = storeShape(shapeOpB); + pars.push_back("opA=" + std::to_string(shapeIdA)); // INT + pars.push_back("opB=" + std::to_string(shapeIdB)); // INT + } else if (shapeType == "Shift") { + const GeoShapeShift* shapeIn = + dynamic_cast<const GeoShapeShift*>(shape); + + // get the referenced Shape used in the 'shift' operation, store it in + // the DB + const GeoShape* shapeOp = shapeIn->getOp(); + const unsigned int shapeId = storeShape(shapeOp); + + // get the Transformation, store it in the DB + GeoTransform* transf = new GeoTransform(shapeIn->getX()); + const unsigned int trId = storeTranform(transf); + + pars.push_back("A=" + std::to_string(shapeId)); // INT + pars.push_back("X=" + std::to_string(trId)); // INT + } else if (shapeType == "Subtraction") { + const GeoShapeSubtraction* shapeIn = + dynamic_cast<const GeoShapeSubtraction*>(shape); + // get the referenced Shape used in the 'union' operation, store it in + // the DB + const GeoShape* shapeOpA = shapeIn->getOpA(); + const unsigned int shapeIdA = storeShape(shapeOpA); + const GeoShape* shapeOpB = shapeIn->getOpB(); + const unsigned int shapeIdB = storeShape(shapeOpB); + pars.push_back("opA=" + std::to_string(shapeIdA)); // INT + pars.push_back("opB=" + std::to_string(shapeIdB)); // INT + } else if (shapeType == "Union") { + const GeoShapeUnion* shapeIn = + dynamic_cast<const GeoShapeUnion*>(shape); + + // get the referenced Shape used in the 'union' operation, store it in + // the DB + const GeoShape* shapeOpA = shapeIn->getOpA(); + unsigned int shapeIdA = storeShape(shapeOpA); + const GeoShape* shapeOpB = shapeIn->getOpB(); + unsigned int shapeIdB = storeShape(shapeOpB); + + pars.push_back("opA=" + std::to_string(shapeIdA)); // INT + pars.push_back("opB=" + std::to_string(shapeIdB)); // INT + } else if (shapeType == "GenericTrap") { + const GeoGenericTrap* shapeIn = + dynamic_cast<const GeoGenericTrap*>(shape); + pars.push_back("ZHalfLength=" + + to_string_with_precision(shapeIn->getZHalfLength())); + pars.push_back("NVertices=" + + to_string_with_precision(shapeIn->getVertices().size())); + for (unsigned long i = 0; i < shapeIn->getVertices().size(); ++i) { + pars.push_back( + "X=" + to_string_with_precision(shapeIn->getVertices()[i](0))); + pars.push_back( + "Y=" + to_string_with_precision(shapeIn->getVertices()[i](1))); + } + } else if (shapeType == "UnidentifiedShape") { + const GeoUnidentifiedShape* shapeIn = + dynamic_cast<const GeoUnidentifiedShape*>(shape); + pars.push_back("name=" + shapeIn->name()); + pars.push_back("asciiData=" + shapeIn->asciiData()); + } + // LAr custom shape + // else if(shapeType == "CustomShape") { + // std::cout << "\n\tWARNING!!! - Use of LArCustomShape is deprecated, + // translating to GeoUnidentifiedShape representation!!\n\n"; const + // LArCustomShape* shapeIn = dynamic_cast<const LArCustomShape*> (shape); + // QStringList pars; + // pars << "name=LArCustomShape"; + // pars << "asciiData="+QString::fromStdString(shapeIn->name()); + // shapePars=pars.join(";"); + // } + else { + std::cout << "\n\tGeoModelWrite -- WARNING!!! - Shape '" << shapeType + << "' needs to be persistified!!\n\n"; + printStdVectorStrings(m_objectsNotPersistified); + } - // Dump the tree volumes into the DB - vol->exec(this); // TODO: check if the new action overwrites the id of the volumes already in the DB...!!! + shapePars = joinVectorStrings(pars, ";"); - } else { - //qDebug() << "The referenced volume has been stored already. Skipping..."; - } - // at the end, we make sure we reset the status - //qDebug() << "setting 'unconnected' to: false"; - m_unconnectedTree = false; + return shapePars; } - -// Get shape parameters -std::string WriteGeoModel::getShapeParameters(const GeoShape* shape) -{ - const std::string shapeType = shape->type(); - - std::string shapePars = ""; - std::vector<std::string> pars; - - if (shapeType == "Box") { - const GeoBox* box = dynamic_cast<const GeoBox*>(shape); - pars.push_back("XHalfLength=" + to_string_with_precision(box->getXHalfLength())) ; - pars.push_back("YHalfLength=" + to_string_with_precision(box->getYHalfLength())) ; - pars.push_back("ZHalfLength=" + to_string_with_precision(box->getZHalfLength())) ; - shapePars = joinVectorStrings(pars,";"); - } else if (shapeType == "Cons") { - const GeoCons* shapeIn = dynamic_cast<const GeoCons*>(shape); - pars.push_back("RMin1=" + to_string_with_precision(shapeIn->getRMin1())) ; - pars.push_back("RMin2=" + to_string_with_precision(shapeIn->getRMin2())) ; - pars.push_back("RMax1=" + to_string_with_precision(shapeIn->getRMax1())) ; - pars.push_back("RMax2=" + to_string_with_precision(shapeIn->getRMax2())) ; - pars.push_back("DZ=" + to_string_with_precision(shapeIn->getDZ())) ; - pars.push_back("SPhi=" + to_string_with_precision(shapeIn->getSPhi())) ; - pars.push_back("DPhi=" + to_string_with_precision(shapeIn->getDPhi())) ; - } else if (shapeType == "Torus") { - // Member Data: - // * Rmax - outside radius of the torus tube - // * Rmin - inside radius of the torus tube (Rmin=0 if not hollow) - // * Rtor - radius of the torus itself - // * - // * SPhi - starting angle of the segment in radians - // * DPhi - delta angle of the segment in radians - // - const GeoTorus* shapeIn = dynamic_cast<const GeoTorus*>(shape); - pars.push_back("Rmin=" + to_string_with_precision(shapeIn->getRMin())) ; - pars.push_back("Rmax=" + to_string_with_precision(shapeIn->getRMax())) ; - pars.push_back("Rtor=" + to_string_with_precision(shapeIn->getRTor())) ; - pars.push_back("SPhi=" + to_string_with_precision(shapeIn->getSPhi())) ; - pars.push_back("DPhi=" + to_string_with_precision(shapeIn->getDPhi())) ; - } - else if (shapeType == "Para") { - const GeoPara* shapeIn = dynamic_cast<const GeoPara*>(shape); - pars.push_back("XHalfLength=" + to_string_with_precision(shapeIn->getXHalfLength())) ; - pars.push_back("YHalfLength=" + to_string_with_precision(shapeIn->getYHalfLength())) ; - pars.push_back("ZHalfLength=" + to_string_with_precision(shapeIn->getZHalfLength())) ; - pars.push_back("Alpha=" + to_string_with_precision(shapeIn->getAlpha())) ; - pars.push_back("Theta=" + to_string_with_precision(shapeIn->getTheta())) ; - pars.push_back("Phi=" + to_string_with_precision(shapeIn->getPhi())) ; - } - else if (shapeType == "Pcon") { - const GeoPcon* shapeIn = dynamic_cast<const GeoPcon*>(shape); - pars.push_back("SPhi=" + to_string_with_precision(shapeIn->getSPhi())); - pars.push_back("DPhi=" + to_string_with_precision(shapeIn->getDPhi())); - // get number of Z planes and loop over them - const int nZplanes = shapeIn->getNPlanes(); - pars.push_back("NZPlanes=" + std::to_string(nZplanes)); //INT - for (int i=0; i<nZplanes; ++i) { - pars.push_back("ZPos=" + to_string_with_precision(shapeIn->getZPlane(i))); - pars.push_back("ZRmin=" + to_string_with_precision(shapeIn->getRMinPlane(i))); - pars.push_back("ZRmax=" + to_string_with_precision(shapeIn->getRMaxPlane(i))); - } - } - else if (shapeType == "Pgon") { - const GeoPgon* shapeIn = dynamic_cast<const GeoPgon*>(shape); - pars.push_back("SPhi=" + to_string_with_precision(shapeIn->getSPhi())) ; - pars.push_back("DPhi=" + to_string_with_precision(shapeIn->getDPhi())) ; - pars.push_back("NSides=" + std::to_string(shapeIn->getNSides())) ; //INT - // get number of Z planes and loop over them - const int nZplanes = shapeIn->getNPlanes(); - pars.push_back("NZPlanes=" + std::to_string(nZplanes)); //INT - for (int i=0; i<nZplanes; ++i) { - pars.push_back("ZPos=" + to_string_with_precision(shapeIn->getZPlane(i))); - pars.push_back("ZRmin=" + to_string_with_precision(shapeIn->getRMinPlane(i))); - pars.push_back("ZRmax=" + to_string_with_precision(shapeIn->getRMaxPlane(i))); - } - } - else if (shapeType == "SimplePolygonBrep") { - const GeoSimplePolygonBrep* shapeIn = dynamic_cast<const GeoSimplePolygonBrep*>(shape); - pars.push_back("DZ=" + to_string_with_precision(shapeIn->getDZ())) ; - // get number of vertices and loop over them - const int nVertices = shapeIn->getNVertices(); - pars.push_back("NVertices=" + std::to_string(nVertices)); //INT - for (int i=0; i<nVertices; ++i) { - pars.push_back("xV=" + to_string_with_precision(shapeIn->getXVertex(i))); - pars.push_back("yV=" + to_string_with_precision(shapeIn->getYVertex(i))); - } - } - else if (shapeType == "Trap") { - const GeoTrap* shapeIn = dynamic_cast<const GeoTrap*>(shape); - pars.push_back("ZHalfLength=" + to_string_with_precision(shapeIn->getZHalfLength())) ; - pars.push_back("Theta=" + to_string_with_precision(shapeIn->getTheta())) ; - pars.push_back("Phi=" + to_string_with_precision(shapeIn->getPhi())) ; - pars.push_back("Dydzn=" + to_string_with_precision(shapeIn->getDydzn())) ; - pars.push_back("Dxdyndzn=" + to_string_with_precision(shapeIn->getDxdyndzn())) ; - pars.push_back("Dxdypdzn=" + to_string_with_precision(shapeIn->getDxdypdzn())) ; - pars.push_back("Angleydzn=" + to_string_with_precision(shapeIn->getAngleydzn())) ; - pars.push_back("Dydzp=" + to_string_with_precision(shapeIn->getDydzp())) ; - pars.push_back("Dxdyndzp=" + to_string_with_precision(shapeIn->getDxdyndzp())) ; - pars.push_back("Dxdypdzp=" + to_string_with_precision(shapeIn->getDxdypdzp())) ; - pars.push_back("Angleydzp=" + to_string_with_precision(shapeIn->getAngleydzp())) ; - } - else if (shapeType == "TwistedTrap") { - - const GeoTwistedTrap* shapeIn = dynamic_cast<const GeoTwistedTrap*>(shape); - pars.push_back("PhiTwist=" + to_string_with_precision(shapeIn->getPhiTwist())) ; - pars.push_back("ZHalfLength=" + to_string_with_precision(shapeIn->getZHalfLength())) ; - pars.push_back("Theta=" + to_string_with_precision(shapeIn->getTheta())) ; - pars.push_back("Phi=" + to_string_with_precision(shapeIn->getPhi())) ; - pars.push_back("DY1HalfLength=" + to_string_with_precision(shapeIn->getY1HalfLength())) ; - pars.push_back("DX1HalfLength=" + to_string_with_precision(shapeIn->getX1HalfLength())) ; - pars.push_back("DX2HalfLength=" + to_string_with_precision(shapeIn->getX2HalfLength())) ; - pars.push_back("DY2HalfLength=" + to_string_with_precision(shapeIn->getY2HalfLength())) ; - pars.push_back("DX3HalfLength=" + to_string_with_precision(shapeIn->getX3HalfLength())) ; - pars.push_back("DX4HalfLength=" + to_string_with_precision(shapeIn->getX4HalfLength())) ; - pars.push_back("DTiltAngleAlpha=" + to_string_with_precision(shapeIn->getTiltAngleAlpha())) ; - - } - else if (shapeType == "Trd") { - const GeoTrd* shapeIn = dynamic_cast<const GeoTrd*>(shape); - pars.push_back("XHalfLength1=" + to_string_with_precision(shapeIn->getXHalfLength1())) ; - pars.push_back("XHalfLength2=" + to_string_with_precision(shapeIn->getXHalfLength2())) ; - pars.push_back("YHalfLength1=" + to_string_with_precision(shapeIn->getYHalfLength1())) ; - pars.push_back("YHalfLength2=" + to_string_with_precision(shapeIn->getYHalfLength2())) ; - pars.push_back("ZHalfLength=" + to_string_with_precision(shapeIn->getZHalfLength())) ; - } - else if (shapeType == "Tube") { - const GeoTube* tube = dynamic_cast<const GeoTube*>(shape); - pars.push_back("RMin=" + to_string_with_precision(tube->getRMin())) ; - pars.push_back("RMax=" + to_string_with_precision(tube->getRMax())) ; - pars.push_back("ZHalfLength=" + to_string_with_precision(tube->getZHalfLength())) ; - } - else if (shapeType == "Tubs") { - const GeoTubs* shapeIn = dynamic_cast<const GeoTubs*>(shape); - pars.push_back("RMin=" + to_string_with_precision(shapeIn->getRMin())) ; - pars.push_back("RMax=" + to_string_with_precision(shapeIn->getRMax())) ; - pars.push_back("ZHalfLength=" + to_string_with_precision(shapeIn->getZHalfLength())) ; - pars.push_back("SPhi=" + to_string_with_precision(shapeIn->getSPhi())) ; - pars.push_back("DPhi=" + to_string_with_precision(shapeIn->getDPhi())) ; - } - else if (shapeType == "TessellatedSolid") { - const GeoTessellatedSolid* shapeIn = dynamic_cast<const GeoTessellatedSolid*>(shape); - // get number of facets - const size_t nFacets = shapeIn->getNumberOfFacets(); - pars.push_back("nFacets=" + std::to_string(nFacets)); //size_t - // loop over the facets - for (size_t i=0; i<nFacets; ++i) { - GeoFacet* facet = shapeIn->getFacet(i); - // get GeoFacet actual implementation - if (dynamic_cast<GeoTriangularFacet*>(facet)) pars.push_back("TRI"); - else if (dynamic_cast<GeoQuadrangularFacet*>(facet)) pars.push_back("QUAD"); - // get vertex type (ABSOLUTE/RELATIVE) - GeoFacet::GeoFacetVertexType facetVertexType = facet->getVertexType(); - if (facetVertexType == GeoFacet::ABSOLUTE) pars.push_back("vT=ABSOLUTE"); - if (facetVertexType == GeoFacet::RELATIVE) pars.push_back("vT=RELATIVE"); - // get number of vertices and loop over them - const size_t nVertices = facet->getNumberOfVertices(); - pars.push_back("nV=" + std::to_string(nVertices)); //size_t - for (size_t i=0; i<nVertices; ++i) { - GeoFacetVertex facetVertex = facet->getVertex(i); - pars.push_back("xV=" + to_string_with_precision( facetVertex[0] )); - pars.push_back("yV=" + to_string_with_precision( facetVertex[1] )); - pars.push_back("zV=" + to_string_with_precision( facetVertex[2] )); - } - } - } - else if (shapeType == "Intersection") { - const GeoShapeIntersection* shapeIn = dynamic_cast<const GeoShapeIntersection*>(shape); - // get the referenced Shape used in the 'union' operation, store it in the DB - const GeoShape* shapeOpA = shapeIn->getOpA(); - const unsigned int shapeIdA = storeShape(shapeOpA); - const GeoShape* shapeOpB = shapeIn->getOpB(); - const unsigned int shapeIdB = storeShape(shapeOpB); - pars.push_back("opA=" + std::to_string( shapeIdA )) ; //INT - pars.push_back("opB=" + std::to_string( shapeIdB )) ; //INT - } - else if (shapeType == "Shift") { - const GeoShapeShift* shapeIn = dynamic_cast<const GeoShapeShift*>(shape); - - // get the referenced Shape used in the 'shift' operation, store it in the DB - const GeoShape* shapeOp = shapeIn->getOp(); - const unsigned int shapeId = storeShape(shapeOp); - - // get the Transformation, store it in the DB - GeoTransform* transf = new GeoTransform( shapeIn->getX() ); - const unsigned int trId = storeTranform(transf); - - pars.push_back("A=" + std::to_string( shapeId )); //INT - pars.push_back("X=" + std::to_string( trId )); //INT - } - else if (shapeType == "Subtraction") { - const GeoShapeSubtraction* shapeIn = dynamic_cast<const GeoShapeSubtraction*>(shape); - // get the referenced Shape used in the 'union' operation, store it in the DB - const GeoShape* shapeOpA = shapeIn->getOpA(); - const unsigned int shapeIdA = storeShape(shapeOpA); - const GeoShape* shapeOpB = shapeIn->getOpB(); - const unsigned int shapeIdB = storeShape(shapeOpB); - pars.push_back("opA=" + std::to_string( shapeIdA )); //INT - pars.push_back("opB=" + std::to_string( shapeIdB )); //INT - } - else if (shapeType == "Union") { - const GeoShapeUnion* shapeIn = dynamic_cast<const GeoShapeUnion*>(shape); - - // get the referenced Shape used in the 'union' operation, store it in the DB - const GeoShape* shapeOpA = shapeIn->getOpA(); - unsigned int shapeIdA = storeShape(shapeOpA); - const GeoShape* shapeOpB = shapeIn->getOpB(); - unsigned int shapeIdB = storeShape(shapeOpB); - - pars.push_back("opA=" + std::to_string( shapeIdA )) ; //INT - pars.push_back("opB=" + std::to_string( shapeIdB )) ; //INT - } - else if (shapeType=="GenericTrap") { - const GeoGenericTrap * shapeIn = dynamic_cast<const GeoGenericTrap*>(shape); - pars.push_back("ZHalfLength=" + to_string_with_precision(shapeIn->getZHalfLength())); - pars.push_back("NVertices=" + to_string_with_precision(shapeIn->getVertices().size())); - for (unsigned long i=0; i<shapeIn->getVertices().size(); ++i) { - pars.push_back("X=" + to_string_with_precision(shapeIn->getVertices()[i](0))); - pars.push_back("Y=" + to_string_with_precision(shapeIn->getVertices()[i](1))); - } - } - else if (shapeType=="UnidentifiedShape") { - const GeoUnidentifiedShape *shapeIn=dynamic_cast<const GeoUnidentifiedShape *> (shape); - pars.push_back("name="+shapeIn->name()); - pars.push_back("asciiData="+shapeIn->asciiData()); - } - //LAr custom shape - // else if(shapeType == "CustomShape") { - // std::cout << "\n\tWARNING!!! - Use of LArCustomShape is deprecated, translating to GeoUnidentifiedShape representation!!\n\n"; - // const LArCustomShape* shapeIn = dynamic_cast<const LArCustomShape*> (shape); - // QStringList pars; - // pars << "name=LArCustomShape"; - // pars << "asciiData="+QString::fromStdString(shapeIn->name()); - // shapePars=pars.join(";"); - // } - else { - std::cout << "\n\tGeoModelWrite -- WARNING!!! - Shape '" << shapeType << "' needs to be persistified!!\n\n"; - printStdVectorStrings(m_objectsNotPersistified); - } - - - shapePars = joinVectorStrings(pars,";"); - - return shapePars; - -} - - -std::vector<double> WriteGeoModel::getTransformParameters(GeoTrf::Transform3D tr) -{ - std::vector<double> vec; +std::vector<double> WriteGeoModel::getTransformParameters( + GeoTrf::Transform3D tr) { + std::vector<double> vec; // get the rotation matrix, the first 3x3 matrix - vec.push_back(tr(0,0)); // xx - vec.push_back(tr(0,1)); // xy - vec.push_back(tr(0,2)); // xz + vec.push_back(tr(0, 0)); // xx + vec.push_back(tr(0, 1)); // xy + vec.push_back(tr(0, 2)); // xz - vec.push_back(tr(1,0)); // yx - vec.push_back(tr(1,1)); // yy - vec.push_back(tr(1,2)); // yz + vec.push_back(tr(1, 0)); // yx + vec.push_back(tr(1, 1)); // yy + vec.push_back(tr(1, 2)); // yz - vec.push_back(tr(2,0)); // zx - vec.push_back(tr(2,1)); // zy - vec.push_back(tr(2,2)); // zz + vec.push_back(tr(2, 0)); // zx + vec.push_back(tr(2, 1)); // zy + vec.push_back(tr(2, 2)); // zz // get the translation vector, i.e. the last column/3vector - vec.push_back(tr(0,3)); // dx - vec.push_back(tr(1,3)); // dy - vec.push_back(tr(2,3)); // dz + vec.push_back(tr(0, 3)); // dx + vec.push_back(tr(1, 3)); // dy + vec.push_back(tr(2, 3)); // dz - return vec; + return vec; } +WriteGeoModel::WriteGeoModel(GMDBManager& db) { + // init variables + m_len = 0; + m_len_nChild = 0; + m_rootVolumeFound = false; + m_unconnectedTree = false; -WriteGeoModel::WriteGeoModel(GMDBManager &db) -{ - // init variables - m_len = 0; - m_len_nChild = 0; - m_rootVolumeFound = false; - m_unconnectedTree = false; - - // get a handle to the database and check it - m_dbManager = &db; - if (m_dbManager->checkIsDBOpen()) { -// if(m_debug) std::cout << "OK! Database is open!" << std::endl; - } - else { - //qDebug() << "Database is not open!"; - } - // initialize the database (create tables, ...) - m_dbManager->initDB(); - // build caches - m_dbManager->loadGeoNodeTypesAndBuildCache(); - // get the database file path - m_dbpath = m_dbManager->getDBFilePath(); - - // get DB metadata - m_memMap_Tables = m_dbManager->getAll_NodeTypesTableIDs(); + // get a handle to the database and check it + m_dbManager = &db; + if (m_dbManager->checkIsDBOpen()) { + if (m_loglevel >= 1) { + std::cout << "OK! Database is open!" << std::endl; + } + } else { + if (m_loglevel >= 1) { + std::cout << "Database is not open!\n"; + } + } + // initialize the database (create tables, ...) + m_dbManager->initDB(); + // build caches + m_dbManager->loadGeoNodeTypesAndBuildCache(); + // get the database file path + m_dbpath = m_dbManager->getDBFilePath(); + + // get DB metadata + m_memMap_Tables = m_dbManager->getAll_NodeTypesTableIDs(); // set verbosity level - m_verbose=0; - if(const char* env_p = std::getenv("GEOMODEL_GEOMODELIO_VERBOSE")) { - std::cout << "GeoModelWrite -- You set the verbosity level to: " << env_p << '\n'; - m_verbose = std::stoi(env_p); + m_loglevel = 0; + std::string envvar = "GEOMODEL_GEOMODELIO_VERBOSE"; + if (const char* env_p = std::getenv(envvar.c_str())) { + std::cout << "GeoModelWrite -- By setting the '" << envvar + << "' env var, you set the verbosity level to: " << env_p + << '\n'; + m_loglevel = std::stoi(env_p); } } -WriteGeoModel::~WriteGeoModel() -{ - // nothing to do so far... +WriteGeoModel::~WriteGeoModel() { + // nothing to do so far... } - -void WriteGeoModel::showMemoryMap() -{ - std::unordered_map<std::string, unsigned int>::const_iterator it = m_memMap.begin(); - while (it != m_memMap.end()) { - std::cout << it->first << ": " << it->second << std::endl; - ++it; - } +void WriteGeoModel::showMemoryMap() { + std::unordered_map<std::string, unsigned int>::const_iterator it = + m_memMap.begin(); + while (it != m_memMap.end()) { + std::cout << it->first << ": " << it->second << std::endl; + ++it; + } } +unsigned int WriteGeoModel::storeObj(const GeoMaterial* pointer, + const std::string& name, + const double& density, + const std::string& elements) { + std::string address = getAddressStringFromPointer(pointer); + unsigned int materialId; + if (!isAddressStored(address)) { + materialId = addMaterial(name, density, elements); + storeAddress(address, materialId); + } else { + materialId = getStoredIdFromAddress(address); + } + return materialId; +} - unsigned int WriteGeoModel::storeObj(const GeoMaterial* pointer, const std::string &name, const double &density, const std::string &elements) -{ - std::string address = getAddressStringFromPointer( pointer ); - unsigned int materialId; +unsigned int WriteGeoModel::storeObj(const GeoElement* pointer, + const std::string& name, + const std::string& symbol, + const double& elZ, const double& elA) { + std::string address = getAddressStringFromPointer(pointer); + unsigned int elementId; - if (! isAddressStored(address)) { - materialId = addMaterial(name, density, elements); - storeAddress( address, materialId ); - } - else { - materialId = getStoredIdFromAddress(address); - } - return materialId; + if (!isAddressStored(address)) { + elementId = addElement(name, symbol, elZ, elA); + storeAddress(address, elementId); + } else { + elementId = getStoredIdFromAddress(address); + } + return elementId; } +unsigned int WriteGeoModel::storeObj(const GeoShape* pointer, + const std::string& name, + const std::string& parameters) { + std::string address = getAddressStringFromPointer(pointer); - unsigned int WriteGeoModel::storeObj(const GeoElement* pointer, const std::string &name, const std::string &symbol, const double &elZ, const double &elA) -{ - std::string address = getAddressStringFromPointer( pointer ); - unsigned int elementId; - - if (! isAddressStored(address)) { - elementId = addElement(name, symbol, elZ, elA); - storeAddress( address, elementId ); - } - else { - elementId = getStoredIdFromAddress(address); - } - return elementId; + unsigned int shapeId; + if (!isAddressStored(address)) { + shapeId = addShape(name, parameters); + storeAddress(address, shapeId); + } else { + shapeId = getStoredIdFromAddress(address); + } + return shapeId; } +unsigned int WriteGeoModel::storeObj(const GeoLogVol* pointer, + const std::string& name, + const unsigned int& shapeId, + const unsigned int& materialId) { + std::string address = getAddressStringFromPointer(pointer); - unsigned int WriteGeoModel::storeObj(const GeoShape* pointer, const std::string &name, const std::string ¶meters) -{ - std::string address = getAddressStringFromPointer( pointer ); - - unsigned int shapeId; - if (! isAddressStored(address)) { - shapeId = addShape(name, parameters); - storeAddress( address, shapeId); - } - else { - shapeId = getStoredIdFromAddress(address); - } - return shapeId; + unsigned int logvolId; + if (!isAddressStored(address)) { + logvolId = addLogVol(name, shapeId, materialId); + storeAddress(address, logvolId); + } else { + logvolId = getStoredIdFromAddress(address); + } + return logvolId; } -unsigned int WriteGeoModel::storeObj(const GeoLogVol* pointer, const std::string &name, const unsigned int &shapeId, const unsigned int &materialId) -{ - std::string address = getAddressStringFromPointer( pointer ); +unsigned int WriteGeoModel::storeObj(const GeoPhysVol* pointer, + const unsigned int& logvolId, + const unsigned int parentId, + const bool isRootVolume) { + std::string address = getAddressStringFromPointer(pointer); + + unsigned int physvolId; + if (!isAddressStored(address)) { + physvolId = addPhysVol(logvolId, parentId, + isRootVolume); // FIXME: remove parentInfo - unsigned int logvolId; - if (! isAddressStored(address)) { - logvolId = addLogVol(name, shapeId, materialId); - storeAddress( address, logvolId ); - } - else { - logvolId = getStoredIdFromAddress(address); - } - return logvolId; + storeAddress(address, physvolId); + } else { + physvolId = getStoredIdFromAddress(address); + } + return physvolId; } +unsigned int WriteGeoModel::storeObj(const GeoFullPhysVol* pointer, + const unsigned int& logvolId, + const unsigned int parentId, + const bool isRootVolume) { + std::string address = getAddressStringFromPointer(pointer); -unsigned int WriteGeoModel::storeObj(const GeoPhysVol* pointer, const unsigned int &logvolId, const unsigned int parentId, const bool isRootVolume) -{ - std::string address = getAddressStringFromPointer( pointer ); + unsigned int physvolId; + if (!isAddressStored(address)) { + physvolId = addFullPhysVol(logvolId, parentId, + isRootVolume); // FIXME: remove parent info! - unsigned int physvolId; - if (! isAddressStored(address)) { - physvolId = addPhysVol(logvolId, parentId, isRootVolume); // FIXME: remove parentInfo - - storeAddress( address, physvolId ); - } - else { - physvolId = getStoredIdFromAddress(address); - } - return physvolId; + storeAddress(address, physvolId); + } else { + physvolId = getStoredIdFromAddress(address); + } + return physvolId; } -unsigned int WriteGeoModel::storeObj(const GeoFullPhysVol* pointer, const unsigned int &logvolId, const unsigned int parentId, const bool isRootVolume) -{ - std::string address = getAddressStringFromPointer( pointer ); - - unsigned int physvolId; - if (! isAddressStored(address)) { - physvolId = addFullPhysVol(logvolId, parentId, isRootVolume); // FIXME: remove parent info! +unsigned int WriteGeoModel::storeObj(const GeoSerialIdentifier* pointer, + const int& baseId) { + const std::string address = getAddressStringFromPointer(pointer); + unsigned int id; - storeAddress( address, physvolId ); - } - else { - physvolId = getStoredIdFromAddress(address); - } - return physvolId; + if (!isAddressStored(address)) { + id = addSerialIdentifier(baseId); + storeAddress(address, id); + } else { + id = getStoredIdFromAddress(address); + } + return id; } -unsigned int WriteGeoModel::storeObj(const GeoSerialIdentifier* pointer, const int &baseId) -{ - const std::string address = getAddressStringFromPointer( pointer ); - unsigned int id; +unsigned int WriteGeoModel::storeObj(const GeoIdentifierTag* pointer, + const int& identifier) { + const std::string address = getAddressStringFromPointer(pointer); + unsigned int id; - if (! isAddressStored(address)) { - id = addSerialIdentifier(baseId); - storeAddress( address, id ); - } - else { - id = getStoredIdFromAddress(address); - } - return id; + if (!isAddressStored(address)) { + id = addIdentifierTag(identifier); + storeAddress(address, id); + } else { + id = getStoredIdFromAddress(address); + } + return id; } -unsigned int WriteGeoModel::storeObj(const GeoIdentifierTag* pointer, const int &identifier) -{ - const std::string address = getAddressStringFromPointer( pointer ); - unsigned int id; +unsigned int WriteGeoModel::storeObj(const GeoSerialDenominator* pointer, + const std::string& baseName) { + const std::string address = getAddressStringFromPointer(pointer); + unsigned int id; - if (! isAddressStored(address)) { - id = addIdentifierTag(identifier); - storeAddress( address, id ); - } - else { - id = getStoredIdFromAddress(address); - } - return id; + if (!isAddressStored(address)) { + id = addSerialDenominator(baseName); + storeAddress(address, id); + } else { + id = getStoredIdFromAddress(address); + } + return id; } +unsigned int WriteGeoModel::storeObj(const GeoSerialTransformer* pointer, + const unsigned int& functionId, + const unsigned int& volId, + const std::string& volType, + const unsigned int& copies) { + const std::string address = getAddressStringFromPointer(pointer); + unsigned int id = 0; -unsigned int WriteGeoModel::storeObj(const GeoSerialDenominator* pointer, const std::string &baseName) -{ - const std::string address = getAddressStringFromPointer( pointer ); - unsigned int id; + if (!isAddressStored(address)) { + id = addSerialTransformer(functionId, volId, volType, copies); + + storeAddress(address, id); + } else { + id = getStoredIdFromAddress(address); + } - if (! isAddressStored(address)) { - id = addSerialDenominator(baseName); - storeAddress( address, id ); - } - else { - id = getStoredIdFromAddress(address); - } - return id; + if (!id) { + std::cout << "ERROR while storing a GeoSerialTransformer! Exiting..." + << std::endl; + exit(EXIT_FAILURE); + } + return id; } +unsigned int WriteGeoModel::storeObj(const GeoXF::Function* pointer, + const std::string& expression) { + const std::string address = getAddressStringFromPointer(pointer); + unsigned int id = 0; -unsigned int WriteGeoModel::storeObj(const GeoSerialTransformer* pointer, const unsigned int &functionId, const unsigned int &volId, const std::string &volType, const unsigned int &copies) -{ - const std::string address = getAddressStringFromPointer( pointer ); - unsigned int id = 0; - - if (! isAddressStored(address)) { - id = addSerialTransformer(functionId, volId, volType, copies); - - storeAddress( address, id ); - } - else { - id = getStoredIdFromAddress(address); - } - - if (!id) { - std::cout << "ERROR while storing a GeoSerialTransformer! Exiting..." << std::endl; - exit(EXIT_FAILURE); - } - return id; -} - -unsigned int WriteGeoModel::storeObj(const GeoXF::Function* pointer, const std::string &expression) -{ - const std::string address = getAddressStringFromPointer( pointer ); - unsigned int id = 0; - - if (! isAddressStored(address)) { - id = addFunction(expression); - - storeAddress( address, id ); - } - else { - id = getStoredIdFromAddress(address); - } - - if (!id) { - std::cout << "ERROR while storing a Function! Exiting..." << std::endl; - exit(EXIT_FAILURE); - } - return id; -} - -unsigned int WriteGeoModel::storeObj(const GeoTransform* pointer, const std::vector<double> ¶meters) -{ - const std::string address = getAddressStringFromPointer( pointer ); - unsigned int id = 0; - - if (! isAddressStored(address)) { - id = addTransform( parameters ); - storeAddress( address, id ); - } - else { - id = getStoredIdFromAddress(address); - } - if (!id) { - std::cout << "ERROR while storing a GeoTransform! Exiting..." << std::endl; - exit(EXIT_FAILURE); - } - return id; -} - -unsigned int WriteGeoModel::storeObj(const GeoAlignableTransform* pointer, const std::vector<double> ¶meters) -{ - const std::string address = getAddressStringFromPointer( pointer ); - unsigned int id = 0; + if (!isAddressStored(address)) { + id = addFunction(expression); + + storeAddress(address, id); + } else { + id = getStoredIdFromAddress(address); + } - if (! isAddressStored(address)) { - id = addAlignableTransform( parameters ); - storeAddress( address, id ); - } - else { - id = getStoredIdFromAddress(address); - } - if (!id) { - std::cout << "ERROR while storing a GeoAlignableTransform! Exiting..." << std::endl; - exit(EXIT_FAILURE); - } - return id; + if (!id) { + std::cout << "ERROR while storing a Function! Exiting..." << std::endl; + exit(EXIT_FAILURE); + } + return id; } +unsigned int WriteGeoModel::storeObj(const GeoTransform* pointer, + const std::vector<double>& parameters) { + const std::string address = getAddressStringFromPointer(pointer); + unsigned int id = 0; - unsigned int WriteGeoModel::storeObj(const GeoNameTag* pointer, const std::string &name) -{ - const std::string address = getAddressStringFromPointer( pointer ); - unsigned int id = 0; + if (!isAddressStored(address)) { + id = addTransform(parameters); + storeAddress(address, id); + } else { + id = getStoredIdFromAddress(address); + } + if (!id) { + std::cout << "ERROR while storing a GeoTransform! Exiting..." + << std::endl; + exit(EXIT_FAILURE); + } + return id; +} + +unsigned int WriteGeoModel::storeObj(const GeoAlignableTransform* pointer, + const std::vector<double>& parameters) { + const std::string address = getAddressStringFromPointer(pointer); + unsigned int id = 0; - if (! isAddressStored(address)) { - id = addNameTag(name); - storeAddress( address, id ); - } - else { - id = getStoredIdFromAddress(address); - } - if (!id) { - std::cout << "ERROR while storing a GeoNameTag! Exiting..." << std::endl; - exit(EXIT_FAILURE); - } - return id; + if (!isAddressStored(address)) { + id = addAlignableTransform(parameters); + storeAddress(address, id); + } else { + id = getStoredIdFromAddress(address); + } + if (!id) { + std::cout << "ERROR while storing a GeoAlignableTransform! Exiting..." + << std::endl; + exit(EXIT_FAILURE); + } + return id; } +unsigned int WriteGeoModel::storeObj(const GeoNameTag* pointer, + const std::string& name) { + const std::string address = getAddressStringFromPointer(pointer); + unsigned int id = 0; + if (!isAddressStored(address)) { + id = addNameTag(name); + storeAddress(address, id); + } else { + id = getStoredIdFromAddress(address); + } + if (!id) { + std::cout << "ERROR while storing a GeoNameTag! Exiting..." + << std::endl; + exit(EXIT_FAILURE); + } + return id; +} + +void WriteGeoModel::storeChildPosition(const unsigned int& parentId, + const std::string& parentType, + const unsigned int& childId, + const unsigned int& parentCopyN, + const unsigned int& childPos, + const std::string& childType, + const unsigned int& childCopyN) { + std::string key = std::to_string(parentId) + ":" + parentType + ":" + + std::to_string(childId) + ":" + childType + ":" + + std::to_string(childPos); + if (m_linkSet.find(key) == m_linkSet.end()) { + addChildPosition( + parentId, parentType, childId, parentCopyN, childPos, childType, + childCopyN); // FIXME: change the positions of the parameters to a + // more logical order, like: parentID, parentType, + // parentCopyN, childPos, ChildType, childId, + // childCopyN + m_linkSet.insert(key); + } +} - void WriteGeoModel::storeChildPosition(const unsigned int &parentId, const std::string &parentType, const unsigned int &childId, const unsigned int &parentCopyN, const unsigned int &childPos, const std::string &childType, const unsigned int &childCopyN) -{ - std::string key=std::to_string(parentId)+":"+parentType+":"+std::to_string(childId)+":"+childType+":"+std::to_string(childPos); - if (m_linkSet.find(key)==m_linkSet.end()) { - addChildPosition(parentId, parentType, childId, parentCopyN, childPos, childType, childCopyN); // FIXME: change the positions of the parameters to a more logical order, like: parentID, parentType, parentCopyN, childPos, ChildType, childId, childCopyN - m_linkSet.insert(key); - } - } +unsigned int WriteGeoModel::addRecord( + std::vector<std::vector<std::string>>* container, + const std::vector<std::string> values) const { + container->push_back(values); + unsigned int idx = + container->size(); // index of pushed element = size after pushing, to + // match ID starting at 1 in the DB + return idx; +} +unsigned int WriteGeoModel::addMaterial(const std::string& name, + const double& density, + const std::string& elements) { + std::vector<std::vector<std::string>>* container = &m_materials; + std::vector<std::string> values; + values.push_back(name); + values.push_back(to_string_with_precision(density)); + values.push_back(elements); + return addRecord(container, values); +} - unsigned int WriteGeoModel::addRecord(std::vector<std::vector<std::string>>* container, const std::vector<std::string> values) const - { - container->push_back(values); - unsigned int idx = container->size(); // index of pushed element = size after pushing, to match ID starting at 1 in the DB - return idx; +unsigned int WriteGeoModel::addElement(const std::string& name, + const std::string& symbol, + const double& elZ, const double& elA) { + std::vector<std::vector<std::string>>* container = &m_elements; + std::vector<std::string> values; + values.insert(values.begin(), {name, symbol, to_string_with_precision(elZ), + to_string_with_precision(elA)}); + return addRecord(container, values); } +unsigned int WriteGeoModel::addNameTag(const std::string& name) { + std::vector<std::vector<std::string>>* container = &m_nameTags; + std::vector<std::string> values; + values.push_back(name); + return addRecord(container, values); +} - unsigned int WriteGeoModel::addMaterial(const std::string &name, const double &density, const std::string &elements) -{ - std::vector<std::vector<std::string>>* container = &m_materials; - std::vector<std::string> values; - values.push_back( name ); - values.push_back( to_string_with_precision(density) ); - values.push_back( elements ); - return addRecord(container, values); +unsigned int WriteGeoModel::addSerialDenominator(const std::string& baseName) { + std::vector<std::vector<std::string>>* container = &m_serialDenominators; + std::vector<std::string> values; + values.push_back(baseName); + return addRecord(container, values); } +unsigned int WriteGeoModel::addSerialIdentifier(const int& baseId) { + std::vector<std::vector<std::string>>* container = &m_serialIdentifiers; + std::vector<std::string> values; + values.push_back(std::to_string(baseId)); + return addRecord(container, values); +/* +<<<<<<< HEAD +} +unsigned int WriteGeoModel::addIdentifierTag(const int& identifier) { + std::vector<std::vector<std::string>>* container = &m_identifierTags; + std::vector<std::string> values; + values.push_back(std::to_string(identifier)); + return addRecord(container, values); +} -unsigned int WriteGeoModel::addElement(const std::string &name, const std::string &symbol, const double &elZ, const double &elA) -{ - std::vector<std::vector<std::string>>* container = &m_elements; - std::vector<std::string> values; - values.insert(values.begin(), { name, symbol, to_string_with_precision(elZ), to_string_with_precision(elA)} ); - return addRecord(container, values); +unsigned int WriteGeoModel::addFunction(const std::string& expression) { + std::vector<std::vector<std::string>>* container = &m_functions; + std::vector<std::string> values; + values.push_back(expression); + return addRecord(container, values); } +unsigned int WriteGeoModel::addAlignableTransform( + const std::vector<double>& params) { + std::vector<std::vector<std::string>>* container = &m_alignableTransforms; + std::vector<std::string> values; + for (const double& par : params) { + values.push_back(to_string_with_precision(par)); + } + return addRecord(container, values); +} -unsigned int WriteGeoModel::addNameTag(const std::string &name) -{ - std::vector<std::vector<std::string>>* container = &m_nameTags; - std::vector<std::string> values; - values.push_back(name); - return addRecord(container, values); +unsigned int WriteGeoModel::addTransform(const std::vector<double>& params) { + std::vector<std::vector<std::string>>* container = &m_transforms; + std::vector<std::string> values; + for (const double& par : params) { + values.push_back(to_string_with_precision(par)); + } + return addRecord(container, values); } -unsigned int WriteGeoModel::addSerialDenominator(const std::string &baseName) -{ - std::vector<std::vector<std::string>>* container = &m_serialDenominators; - std::vector<std::string> values; - values.push_back(baseName); - return addRecord(container, values); +unsigned int WriteGeoModel::getIdFromNodeType(const std::string& nodeType) { + std::unordered_map<std::string, unsigned int>::iterator it = + m_memMap_Tables.find(nodeType); + if (it != m_memMap_Tables.end()) { // item found + return m_memMap_Tables.at(nodeType); + } + return 0; // item not found } -unsigned int WriteGeoModel::addSerialIdentifier(const int &baseId) -{ - std::vector<std::vector<std::string>>* container = &m_serialIdentifiers; - std::vector<std::string> values; - values.push_back( std::to_string(baseId) ); - return addRecord(container, values); +unsigned int WriteGeoModel::addSerialTransformer(const unsigned int& funcId, + const unsigned int& physvolId, + const std::string volType, + const unsigned int& copies) { + std::vector<std::vector<std::string>>* container = &m_serialTransformers; + const unsigned int volTypeID = getIdFromNodeType(volType); + + std::vector<std::string> values; + values.insert(values.begin(), + {std::to_string(funcId), std::to_string(physvolId), + std::to_string(volTypeID), std::to_string(copies)}); // INT + + return addRecord(container, values); } -unsigned int WriteGeoModel::addIdentifierTag(const int &identifier) -{ - std::vector<std::vector<std::string>>* container = &m_identifierTags; - std::vector<std::string> values; - values.push_back( std::to_string(identifier) ); - return addRecord(container, values); +unsigned int WriteGeoModel::addShape(const std::string& type, + const std::string& parameters) { + std::vector<std::vector<std::string>>* container = &m_shapes; + std::vector<std::string> values; + values.push_back(type); + values.push_back(parameters); + return addRecord(container, values); } -unsigned int WriteGeoModel::addFunction(const std::string &expression) -{ - std::vector<std::vector<std::string>>* container = &m_functions; - std::vector<std::string> values; - values.push_back(expression); - return addRecord(container, values); +unsigned int WriteGeoModel::addPhysVol(const unsigned int& logVolId, + const unsigned int& //parentPhysVolId + , + const bool& isRootVolume) { + std::vector<std::vector<std::string>>* container = &m_physVols; + std::vector<std::string> values; + values.push_back(std::to_string(logVolId)); // INT + unsigned int idx = addRecord(container, values); + + if (isRootVolume) { + std::vector<std::string> rootValues; + rootValues.insert(rootValues.begin(), + {std::to_string(idx), "GeoPhysVol"}); // INT + m_rootVolume = rootValues; + } + + return idx; } +unsigned int WriteGeoModel::addFullPhysVol( + const unsigned int& logVolId, const unsigned int& //parentPhysVolId// +, + const bool& isRootVolume) { + std::vector<std::vector<std::string>>* container = &m_fullPhysVols; + std::vector<std::string> values; + values.push_back(std::to_string(logVolId)); // INT + unsigned int idx = addRecord(container, values); + + if (isRootVolume) { + std::vector<std::string> rootValues; + rootValues.insert(rootValues.begin(), + {std::to_string(idx), "GeoFullPhysVol"}); // INT + m_rootVolume = rootValues; + } -unsigned int WriteGeoModel::addAlignableTransform(const std::vector<double> ¶ms) -{ - std::vector<std::vector<std::string>>* container = &m_alignableTransforms; - std::vector<std::string> values; - for(const double& par : params) { - values.push_back( to_string_with_precision(par) ); - } - return addRecord(container, values); + return idx; } +unsigned int WriteGeoModel::addLogVol(const std::string& name, + const unsigned int& shapeId, + const unsigned int& materialId) { + std::vector<std::vector<std::string>>* container = &m_logVols; + std::vector<std::string> values; + values.insert(values.begin(), {name, std::to_string(shapeId), + std::to_string(materialId)}); // INT + return addRecord(container, values); +} + +void WriteGeoModel::addChildPosition(const unsigned int& parentId, + const std::string& parentType, + const unsigned int& childId, + const unsigned int& parentCopyN, + const unsigned int& childPos, + const std::string& childType, + const unsigned int& childCopyN) { + std::vector<std::vector<std::string>>* container = &m_childrenPositions; + const unsigned int parentTableID = getIdFromNodeType(parentType); + const unsigned int childTableID = getIdFromNodeType(childType); + std::vector<std::string> values; + // values << parentId.toString() << parentTableID << + // QString::number(parentCopyN) << QString::number(childPos) << + // childTableID << childId.toString() << QString::number(childCopyN); + values.insert(values.begin(), + {std::to_string(parentId), std::to_string(parentTableID), + std::to_string(parentCopyN), std::to_string(childPos), + std::to_string(childTableID), std::to_string(childId), + std::to_string(childCopyN)}); // INT + addRecord(container, values); + return; +} -unsigned int WriteGeoModel::addTransform(const std::vector<double> ¶ms) -{ - std::vector<std::vector<std::string>>* container = &m_transforms; - std::vector<std::string> values; - for(const double& par : params) { - values.push_back( to_string_with_precision(par) ); - } - return addRecord(container, values); +// +// The 'publisher' parameter is optional, by default it is set to 'nullptr' in +// the header. +void WriteGeoModel::saveToDB(GeoPublisher* publisher) { + if (!m_inspect) { + std::vector<GeoPublisher*> vec; + if (publisher) vec.push_back(publisher); + saveToDB(vec); + } else { + std::cerr + << "\n\nWARNING! You called the 'saveToDB' method, but " + "WriteGeoModel has been constructed by calling the 'inspect' " + "contructor! Use the 'db' constructor, instead.\n\n" + << std::endl; + exit(EXIT_FAILURE); + } } +// +// Note: The vector of GeoPublishers is completely optional, it is empty by +// default and not handled. +void WriteGeoModel::saveToDB(std::vector<GeoPublisher*>& publishers) { + if (!m_inspect) { + std::cout << "Saving the GeoModel tree to file: '" << m_dbpath << "'" + << std::endl; + + m_dbManager->addListOfRecords("GeoMaterial", m_materials); + m_dbManager->addListOfRecords("GeoElement", m_elements); + m_dbManager->addListOfRecords("GeoNameTag", m_nameTags); + m_dbManager->addListOfRecords("GeoAlignableTransform", + m_alignableTransforms); + m_dbManager->addListOfRecords("GeoTransform", m_transforms); + m_dbManager->addListOfRecords("Function", m_functions); + m_dbManager->addListOfRecords("GeoSerialTransformer", + m_serialTransformers); + m_dbManager->addListOfRecords("GeoShape", m_shapes); + m_dbManager->addListOfRecords("GeoSerialDenominator", + m_serialDenominators); + m_dbManager->addListOfRecords("GeoSerialIdentifier", + m_serialIdentifiers); + m_dbManager->addListOfRecords("GeoIdentifierTag", m_identifierTags); + m_dbManager->addListOfRecords("GeoPhysVol", m_physVols); + m_dbManager->addListOfRecords("GeoFullPhysVol", m_fullPhysVols); + m_dbManager->addListOfRecords("GeoLogVol", m_logVols); + + m_dbManager->addListOfChildrenPositions(m_childrenPositions); + m_dbManager->addRootVolume(m_rootVolume); + + // save data stored in instances of GeoPublisher + if (publishers.size()) { + std::cout + << "\nINFO: A pointer to a GeoPublisher instance has been " + "provided, " + << "so we dump the published list of FullPhysVol and " + "AlignableTransforms nodes and auxiliary data, if any.\n" + << std::endl; + for (GeoPublisher* publisher : publishers) { + storePublishedNodes(publisher); + storePublishedAuxiliaryData(publisher); + } + } - unsigned int WriteGeoModel::getIdFromNodeType( const std::string &nodeType ) -{ - std::unordered_map<std::string, unsigned int>::iterator it = m_memMap_Tables.find(nodeType); - if ( it != m_memMap_Tables.end() ) { // item found - return m_memMap_Tables.at(nodeType); - } - return 0; // item not found + // save auxiliary data stored through WriteGeoModel directly + //if ( m_auxiliaryTablesStr.size() ) { + // std::cout << "\nINFO: Custom tables to store auxiliary data + //have been added, " + // << "so we create these custom tables in the DB:" + // << std::endl; + // for ( auto& tableData : m_auxiliaryTablesStr ) { + // std::cout << "\tsaving table: " << tableData.first << std::endl; + // m_dbManager->createCustomTable( tableData.first, + //(tableData.second).first, (tableData.second).second, + //m_auxiliaryTablesStrData[ tableData.first ] ); + // } + //} + if (m_auxiliaryTablesVar.size()) { + if (m_loglevel > 0) { + std::cout + << "\nINFO: Custom tables to store auxiliary data have " + "been added, " + << "so we create these custom tables in the DB:" + << std::endl; + } + for (auto& tableData : m_auxiliaryTablesVar) { + if (m_loglevel > 0) { + std::cout << "\nsaving table: " << tableData.first + << std::endl; + } + m_dbManager->createCustomTable( + tableData.first, (tableData.second).first, + (tableData.second).second, + m_auxiliaryTablesVarData[tableData.first]); + } + } + + if (!m_objectsNotPersistified.empty()) { + std::cout + << "\n\tGeoModelWrite -- WARNING!! There are shapes/nodes " + "which need to be persistified! --> "; + printStdVectorStrings(m_objectsNotPersistified); + std::cout << "\n\n"; + } + + return; + + } else { + std::cerr + << "\n\nWARNING! You called the 'saveToDB' method, but " + "WriteGeoModel has been constructed by calling the 'inspect' " + "contructor! Use the 'db' constructor, instead.\n\n" + << std::endl; + exit(EXIT_FAILURE); + } } - unsigned int WriteGeoModel::addSerialTransformer(const unsigned int &funcId, const unsigned int &physvolId, const std::string volType, const unsigned int &copies) -{ - std::vector<std::vector<std::string>>* container = &m_serialTransformers; - const unsigned int volTypeID = getIdFromNodeType(volType); +void WriteGeoModel::storePublishedAuxiliaryData(GeoPublisher* publisher) { + AuxTableDefs tableDefs = publisher->getPublishedAuxData().first; + AuxTableData tableAuxData = publisher->getPublishedAuxData().second; + if (tableDefs.size()) { + std::cout << "\nINFO: Custom tables to store auxiliary data have been " + "added to an instance of GeoPublisher, " + << "so we create these custom tables in the DB:" << std::endl; + for (auto& tableData : tableDefs) { + if (m_loglevel > 0) { + std::cout << "\nsaving table: " << tableData.first << std::endl; + } + m_dbManager->createCustomTable( + tableData.first, (tableData.second).first, + (tableData.second).second, tableAuxData[tableData.first]); + } + } +} - std::vector<std::string> values; - values.insert( values.begin(), {std::to_string(funcId), std::to_string(physvolId), std::to_string(volTypeID), std::to_string(copies)} ); //INT +======= +*/ +} - return addRecord(container, values); +unsigned int WriteGeoModel::addIdentifierTag(const int& identifier) { + std::vector<std::vector<std::string>>* container = &m_identifierTags; + std::vector<std::string> values; + values.push_back(std::to_string(identifier)); + return addRecord(container, values); } - unsigned int WriteGeoModel::addShape(const std::string &type, const std::string ¶meters) -{ - std::vector<std::vector<std::string>>* container = &m_shapes; - std::vector<std::string> values; - values.push_back(type); - values.push_back(parameters); - return addRecord(container, values); +unsigned int WriteGeoModel::addFunction(const std::string& expression) { + std::vector<std::vector<std::string>>* container = &m_functions; + std::vector<std::string> values; + values.push_back(expression); + return addRecord(container, values); } +unsigned int WriteGeoModel::addAlignableTransform( + const std::vector<double>& params) { + std::vector<std::vector<std::string>>* container = &m_alignableTransforms; + std::vector<std::string> values; + for (const double& par : params) { + values.push_back(to_string_with_precision(par)); + } + return addRecord(container, values); +} -unsigned int WriteGeoModel::addPhysVol(const unsigned int &logVolId, const unsigned int & /*parentPhysVolId*/, const bool &isRootVolume) -{ - std::vector<std::vector<std::string>>* container = &m_physVols; +unsigned int WriteGeoModel::addTransform(const std::vector<double>& params) { + std::vector<std::vector<std::string>>* container = &m_transforms; std::vector<std::string> values; - values.push_back( std::to_string(logVolId) ); //INT - unsigned int idx = addRecord(container, values); - if (isRootVolume) { - std::vector<std::string> rootValues; - rootValues.insert(rootValues.begin(), { std::to_string(idx), "GeoPhysVol"} ); //INT - m_rootVolume = rootValues; - } - return idx; + for (const double& par : params) { + values.push_back(to_string_with_precision(par)); + } + return addRecord(container, values); } +unsigned int WriteGeoModel::getIdFromNodeType(const std::string& nodeType) { + std::unordered_map<std::string, unsigned int>::iterator it = + m_memMap_Tables.find(nodeType); + if (it != m_memMap_Tables.end()) { // item found + return m_memMap_Tables.at(nodeType); + } + return 0; // item not found +} -unsigned int WriteGeoModel::addFullPhysVol(const unsigned int &logVolId, const unsigned int & /*parentPhysVolId*/, const bool &isRootVolume) -{ - std::vector<std::vector<std::string>>* container = &m_fullPhysVols; - std::vector<std::string> values; - values.push_back( std::to_string(logVolId) ); //INT - unsigned int idx = addRecord(container, values); - if (isRootVolume) { - std::vector<std::string> rootValues; -// rootValues << QString::number(idx) << "GeoFullPhysVol"; - rootValues.insert(rootValues.begin(), { std::to_string(idx), "GeoPhysVol"} ); //INT - m_rootVolume = rootValues; - } - return idx; -} - -unsigned int WriteGeoModel::addLogVol(const std::string &name, const unsigned int &shapeId, const unsigned int &materialId) -{ - std::vector<std::vector<std::string>>* container = &m_logVols; - std::vector<std::string> values; - values.insert( values.begin(), {name, std::to_string(shapeId), std::to_string(materialId)} ); //INT - return addRecord(container, values); +unsigned int WriteGeoModel::addSerialTransformer(const unsigned int& funcId, + const unsigned int& physvolId, + const std::string volType, + const unsigned int& copies) { + std::vector<std::vector<std::string>>* container = &m_serialTransformers; + const unsigned int volTypeID = getIdFromNodeType(volType); + + std::vector<std::string> values; + values.insert(values.begin(), + {std::to_string(funcId), std::to_string(physvolId), + std::to_string(volTypeID), std::to_string(copies)}); // INT + + return addRecord(container, values); } +unsigned int WriteGeoModel::addShape(const std::string& type, + const std::string& parameters) { + std::vector<std::vector<std::string>>* container = &m_shapes; + std::vector<std::string> values; + values.push_back(type); + values.push_back(parameters); + return addRecord(container, values); +} - void WriteGeoModel::addChildPosition(const unsigned int &parentId, const std::string &parentType, const unsigned int &childId, const unsigned int &parentCopyN, const unsigned int &childPos, const std::string &childType, const unsigned int &childCopyN) -{ - std::vector<std::vector<std::string>>* container = &m_childrenPositions; - const unsigned int parentTableID = getIdFromNodeType(parentType); - const unsigned int childTableID = getIdFromNodeType(childType); +unsigned int WriteGeoModel::addPhysVol(const unsigned int& logVolId, + const unsigned int& /*parentPhysVolId*/, + const bool& isRootVolume) { + std::vector<std::vector<std::string>>* container = &m_physVols; + std::vector<std::string> values; + values.push_back(std::to_string(logVolId)); // INT + unsigned int idx = addRecord(container, values); + if (isRootVolume) { + std::vector<std::string> rootValues; + rootValues.insert(rootValues.begin(), + {std::to_string(idx), "GeoPhysVol"}); // INT + m_rootVolume = rootValues; + } + return idx; +} - std::vector<std::string> values; -// values << parentId.toString() << parentTableID << QString::number(parentCopyN) << QString::number(childPos) << childTableID << childId.toString() << QString::number(childCopyN); - values.insert(values.begin(), { std::to_string(parentId), std::to_string(parentTableID), std::to_string(parentCopyN), std::to_string(childPos), std::to_string(childTableID), std::to_string(childId), std::to_string(childCopyN)} ); //INT - addRecord(container, values); - return; +unsigned int WriteGeoModel::addFullPhysVol( + const unsigned int& logVolId, const unsigned int& /*parentPhysVolId*/, + const bool& isRootVolume) { + std::vector<std::vector<std::string>>* container = &m_fullPhysVols; + std::vector<std::string> values; + values.push_back(std::to_string(logVolId)); // INT + unsigned int idx = addRecord(container, values); + if (isRootVolume) { + std::vector<std::string> rootValues; + rootValues.insert(rootValues.begin(), + {std::to_string(idx), "GeoFullPhysVol"}); // INT + m_rootVolume = rootValues; + } + return idx; } +unsigned int WriteGeoModel::addLogVol(const std::string& name, + const unsigned int& shapeId, + const unsigned int& materialId) { + std::vector<std::vector<std::string>>* container = &m_logVols; + std::vector<std::string> values; + values.insert(values.begin(), {name, std::to_string(shapeId), + std::to_string(materialId)}); // INT + return addRecord(container, values); +} + +void WriteGeoModel::addChildPosition(const unsigned int& parentId, + const std::string& parentType, + const unsigned int& childId, + const unsigned int& parentCopyN, + const unsigned int& childPos, + const std::string& childType, + const unsigned int& childCopyN) { + std::vector<std::vector<std::string>>* container = &m_childrenPositions; + const unsigned int parentTableID = getIdFromNodeType(parentType); + const unsigned int childTableID = getIdFromNodeType(childType); + + std::vector<std::string> values; + // values << parentId.toString() << parentTableID << + // QString::number(parentCopyN) << QString::number(childPos) << + // childTableID << childId.toString() << QString::number(childCopyN); + values.insert(values.begin(), + {std::to_string(parentId), std::to_string(parentTableID), + std::to_string(parentCopyN), std::to_string(childPos), + std::to_string(childTableID), std::to_string(childId), + std::to_string(childCopyN)}); // INT + addRecord(container, values); + return; +} /* - * The 'publisher' parameter is optional, by default it is set to 'nullptr' in the header. + * The 'publisher' parameter is optional, by default it is set to 'nullptr' in + * the header. */ -void WriteGeoModel::saveToDB( GeoPublisher* publisher ) -{ +void WriteGeoModel::saveToDB(GeoPublisher* publisher) { std::vector<GeoPublisher*> vec; - if( publisher ) - vec.push_back(publisher); + if (publisher) vec.push_back(publisher); saveToDB(vec); } /* - * Note: The vector of GeoPublishers is completely optional, it is empty by default and not handled. + * Note: The vector of GeoPublishers is completely optional, it is empty by + * default and not handled. */ -void WriteGeoModel::saveToDB( std::vector<GeoPublisher*>& publishers ) -{ - std::cout << "Saving the GeoModel tree to file: '" << m_dbpath << "'" << std::endl; - - m_dbManager->addListOfRecords("GeoMaterial", m_materials); - m_dbManager->addListOfRecords("GeoElement", m_elements); - m_dbManager->addListOfRecords("GeoNameTag", m_nameTags); - m_dbManager->addListOfRecords("GeoAlignableTransform", m_alignableTransforms); - m_dbManager->addListOfRecords("GeoTransform", m_transforms); - m_dbManager->addListOfRecords("Function", m_functions); - m_dbManager->addListOfRecords("GeoSerialTransformer", m_serialTransformers); - m_dbManager->addListOfRecords("GeoShape", m_shapes); - m_dbManager->addListOfRecords("GeoSerialDenominator", m_serialDenominators); - m_dbManager->addListOfRecords("GeoSerialIdentifier", m_serialIdentifiers); - m_dbManager->addListOfRecords("GeoIdentifierTag", m_identifierTags); - m_dbManager->addListOfRecords("GeoPhysVol", m_physVols); - m_dbManager->addListOfRecords("GeoFullPhysVol", m_fullPhysVols); - m_dbManager->addListOfRecords("GeoLogVol", m_logVols); - - m_dbManager->addListOfChildrenPositions(m_childrenPositions); - m_dbManager->addRootVolume(m_rootVolume); +void WriteGeoModel::saveToDB(std::vector<GeoPublisher*>& publishers) { + std::cout << "Saving the GeoModel tree to file: '" << m_dbpath << "'" + << std::endl; + + m_dbManager->addListOfRecords("GeoMaterial", m_materials); + m_dbManager->addListOfRecords("GeoElement", m_elements); + m_dbManager->addListOfRecords("GeoNameTag", m_nameTags); + m_dbManager->addListOfRecords("GeoAlignableTransform", + m_alignableTransforms); + m_dbManager->addListOfRecords("GeoTransform", m_transforms); + m_dbManager->addListOfRecords("Function", m_functions); + m_dbManager->addListOfRecords("GeoSerialTransformer", m_serialTransformers); + m_dbManager->addListOfRecords("GeoShape", m_shapes); + m_dbManager->addListOfRecords("GeoSerialDenominator", m_serialDenominators); + m_dbManager->addListOfRecords("GeoSerialIdentifier", m_serialIdentifiers); + m_dbManager->addListOfRecords("GeoIdentifierTag", m_identifierTags); + m_dbManager->addListOfRecords("GeoPhysVol", m_physVols); + m_dbManager->addListOfRecords("GeoFullPhysVol", m_fullPhysVols); + m_dbManager->addListOfRecords("GeoLogVol", m_logVols); + + m_dbManager->addListOfChildrenPositions(m_childrenPositions); + m_dbManager->addRootVolume(m_rootVolume); // save data stored in instances of GeoPublisher - if(publishers.size()) { - std::cout << "\nINFO: A pointer to a GeoPublisher instance has been provided, " - << "so we dump the published list of FullPhysVol and AlignableTransforms nodes and auxiliary data, if any.\n" - << std::endl; - for(GeoPublisher* publisher : publishers) { + if (publishers.size()) { + std::cout << "\nINFO: A pointer to a GeoPublisher instance has been " + "provided, " + << "so we dump the published list of FullPhysVol and " + "AlignableTransforms nodes and auxiliary data, if any.\n" + << std::endl; + for (GeoPublisher* publisher : publishers) { storePublishedNodes(publisher); storePublishedAuxiliaryData(publisher); } - } + } // save auxiliary data stored through WriteGeoModel directly /* if ( m_auxiliaryTablesStr.size() ) { - std::cout << "\nINFO: Custom tables to store auxiliary data have been added, " - << "so we create these custom tables in the DB:" - << std::endl; + std::cout << "\nINFO: Custom tables to store auxiliary data have + been added, " + << "so we create these custom tables in the DB:" + << std::endl; for ( auto& tableData : m_auxiliaryTablesStr ) { - std::cout << "\tsaving table: " << tableData.first << std::endl; - m_dbManager->createCustomTable( tableData.first, (tableData.second).first, (tableData.second).second, m_auxiliaryTablesStrData[ tableData.first ] ); + std::cout << "\tsaving table: " << tableData.first << std::endl; + m_dbManager->createCustomTable( tableData.first, + (tableData.second).first, (tableData.second).second, + m_auxiliaryTablesStrData[ tableData.first ] ); } }*/ - if ( m_auxiliaryTablesVar.size() ) { - if (m_verbose>0) { - std::cout << "\nINFO: Custom tables to store auxiliary data have been added, " - << "so we create these custom tables in the DB:" - << std::endl; + if (m_auxiliaryTablesVar.size()) { + if (m_loglevel >= 0) { + std::cout << "\nINFO: Custom tables to store auxiliary data have " + "been added, " + << "so we create these custom tables in the DB:" + << std::endl; + } + for (auto& tableData : m_auxiliaryTablesVar) { + if (m_loglevel >= 1) { + std::cout << "\nsaving table: " << tableData.first << std::endl; + } + m_dbManager->createCustomTable( + tableData.first, (tableData.second).first, + (tableData.second).second, + m_auxiliaryTablesVarData[tableData.first]); } - for ( auto& tableData : m_auxiliaryTablesVar ) { - if (m_verbose>0) { std::cout << "\nsaving table: " << tableData.first << std::endl; } - m_dbManager->createCustomTable( tableData.first, (tableData.second).first, (tableData.second).second, m_auxiliaryTablesVarData[ tableData.first ] ); - } } - - if ( !m_objectsNotPersistified.empty() ) { - std::cout << "\n\tGeoModelWrite -- WARNING!! There are shapes/nodes which need to be persistified! --> "; + if (!m_objectsNotPersistified.empty()) { + std::cout << "\n\tGeoModelWrite -- WARNING!! There are shapes/nodes " + "which need to be persistified! --> "; printStdVectorStrings(m_objectsNotPersistified); std::cout << "\n\n"; - } + } - return; + return; } -void WriteGeoModel::storePublishedAuxiliaryData(GeoPublisher* publisher) -{ +void WriteGeoModel::storePublishedAuxiliaryData(GeoPublisher* publisher) { AuxTableDefs tableDefs = publisher->getPublishedAuxData().first; AuxTableData tableAuxData = publisher->getPublishedAuxData().second; - if ( tableDefs.size() ) { - - std::cout << "\nINFO: Custom tables to store auxiliary data have been added to an instance of GeoPublisher, " - << "so we create these custom tables in the DB:" - << std::endl; - for ( auto& tableData : tableDefs ) { - if(m_verbose>0) { std::cout << "\nsaving table: " << tableData.first << std::endl; } - m_dbManager->createCustomTable( tableData.first, (tableData.second).first, (tableData.second).second, tableAuxData[ tableData.first ] ); - } + if (tableDefs.size()) { + std::cout << "\nINFO: Custom tables to store auxiliary data have been " + "added to an instance of GeoPublisher, " + << "so we create these custom tables in the DB:" << std::endl; + for (auto& tableData : tableDefs) { + if (m_loglevel >= 1) { + std::cout << "\nsaving table: " << tableData.first << std::endl; + } + m_dbManager->createCustomTable( + tableData.first, (tableData.second).first, + (tableData.second).second, tableAuxData[tableData.first]); + } } - } -void WriteGeoModel::storePublishedNodes(GeoPublisher* store) -{ - // loop over the published AlignableTransform nodes - std::map<GeoAlignableTransform*, std::any> mapAXF = store->getPublishedAXF(); - storeRecordPublishedNodes<std::map<GeoAlignableTransform*, std::any>>(mapAXF, &m_publishedAlignableTransforms_String); +//>>>>>>> origin + + +void WriteGeoModel::storePublishedNodes(GeoPublisher* store) { + // loop over the published AlignableTransform nodes + std::map<GeoAlignableTransform*, std::any> mapAXF = + store->getPublishedAXF(); + storeRecordPublishedNodes<std::map<GeoAlignableTransform*, std::any>>( + mapAXF, &m_publishedAlignableTransforms_String); // loop over the published GeoVFullPhysVol nodes std::map<GeoVFullPhysVol*, std::any> mapFPV = store->getPublishedFPV(); - storeRecordPublishedNodes<std::map<GeoVFullPhysVol*, std::any>>(mapFPV, &m_publishedFullPhysVols_String); + storeRecordPublishedNodes<std::map<GeoVFullPhysVol*, std::any>>( + mapFPV, &m_publishedFullPhysVols_String); // save the list of matching published nodes to the DB std::string storeName = store->getName(); if (mapAXF.size() > 0) { - m_dbManager->addListOfPublishedAlignableTransforms(m_publishedAlignableTransforms_String, storeName); + m_dbManager->addListOfPublishedAlignableTransforms( + m_publishedAlignableTransforms_String, storeName); } else { - std::cout << "\nGeoModelWrite -- WARNING! A pointer to a GeoPublisher was provided, but no GeoAlignableTransform nodes have been published. Please, check if that was intended. (If in doubt, please ask to 'geomodel-developers@cern.ch')\n" << std::endl; + std::cout << "\nGeoModelWrite -- WARNING! A pointer to a GeoPublisher " + "was provided, but no GeoAlignableTransform nodes have " + "been published. Please, check if that was intended. (If " + "in doubt, please ask to 'geomodel-developers@cern.ch')\n" + << std::endl; } if (mapFPV.size() > 0) { - m_dbManager->addListOfPublishedFullPhysVols(m_publishedFullPhysVols_String, storeName); + m_dbManager->addListOfPublishedFullPhysVols( + m_publishedFullPhysVols_String, storeName); } else { - std::cout << "\nGeoModelWrite -- WARNING! A pointer to a GeoPublisher was provided, but no GeoFullPhysVol nodes have been published. Please, check if that was intended. (If in doubt, please ask to 'geomodel-developers@cern.ch')\n" << std::endl; + std::cout << "\nGeoModelWrite -- WARNING! A pointer to a GeoPublisher " + "was provided, but no GeoFullPhysVol nodes have been " + "published. Please, check if that was intended. (If in " + "doubt, please ask to 'geomodel-developers@cern.ch')\n" + << std::endl; } // clear the caches @@ -1776,193 +2205,206 @@ void WriteGeoModel::storePublishedNodes(GeoPublisher* store) m_publishedFullPhysVols_String.clear(); } -template <typename TT> void WriteGeoModel::storeRecordPublishedNodes(const TT storeMap, std::vector<std::vector<std::string>>* cachePublishedNodes ) -{ - // NOTE: We store all keys as strings, independently of their original format. - // However, we store the original format as well, - // so we will be able to convert the keys to their original format when clients will read them back. +template <typename TT> +void WriteGeoModel::storeRecordPublishedNodes( + const TT storeMap, + std::vector<std::vector<std::string>>* cachePublishedNodes) { + // NOTE: We store all keys as strings, independently of their original + // format. + // However, we store the original format as well, + // so we will be able to convert the keys to their original format + // when clients will read them back. // - for( const auto& [vol, key ] : storeMap ) - { + for (const auto& [vol, key] : storeMap) { auto& keyType = key.type(); // get key type and convert to std::string to store into the cache std::string keyStr; std::string keyTypeStr; - if ( typeid(std::string) == keyType ) { + if (typeid(std::string) == keyType) { keyTypeStr = "string"; keyStr = std::any_cast<std::string>(key); - } - else if ( typeid(int) == keyType ) { + } else if (typeid(int) == keyType) { keyTypeStr = "int"; - keyStr = std::to_string( std::any_cast<int>(key) ); - } - else if ( typeid(unsigned) == keyType ) { + keyStr = std::to_string(std::any_cast<int>(key)); + } else if (typeid(unsigned) == keyType) { keyTypeStr = "uint"; - keyStr = std::to_string( std::any_cast<unsigned>(key) ); - } - else { - std::cout << "ERROR! The type of the key used to publish FPV and AXF nodes is not 'std::string', nor 'int', nor 'unsigned int'. Format not supported, at the moment..\n" - << "If in doubt, please ask to 'geomodel-developers@cern.ch'. Exiting...\n\n"; + keyStr = std::to_string(std::any_cast<unsigned>(key)); + } else { + std::cout + << "ERROR! The type of the key used to publish FPV and AXF " + "nodes is not 'std::string', nor 'int', nor 'unsigned int'. " + "Format not supported, at the moment..\n" + << "If in doubt, please ask to 'geomodel-developers@cern.ch'. " + "Exiting...\n\n"; exit(EXIT_FAILURE); } - // check if address is stored already; and get the ID associated with it. - // NOTE: All of the addresses should be stored already, at this stage. + // check if address is stored already; and get the ID associated with + // it. NOTE: All of the addresses should be stored already, at this + // stage. // If not, there's a serious bug! unsigned int volID = 0; - std::string volStr = getAddressStringFromPointer( vol ); - if( isAddressStored(volStr) ) { + std::string volStr = getAddressStringFromPointer(vol); + if (isAddressStored(volStr)) { volID = getStoredIdFromAddress(volStr); } else { - std::cout << "ERROR!!! Address of node is not stored, but it should! Ask 'geomodel-developers@cern.ch'. Exiting...\n\n"; + std::cout + << "ERROR!!! Address of node is not stored, but it should! Ask " + "'geomodel-developers@cern.ch'. Exiting...\n\n"; exit(EXIT_FAILURE); } // debug msg - //std::cout << vol << "::" << keyStr << " [" << keyTypeStr << "] --> " << volID << std::endl; + if (m_loglevel >= 2) { + std::cout << vol << "::" << keyStr << " [" << keyTypeStr << "] --> " + << volID << std::endl; + } - // prepare the vector containing the pieces of information to be stored in the DB table + // prepare the vector containing the pieces of information to be stored + // in the DB table std::vector<std::string> values; values.push_back(keyStr); values.push_back(std::to_string(volID)); - values.push_back(keyTypeStr); // TODO: store the key type in a metadata table, not in the records' table; so it can be stored once only. + values.push_back(keyTypeStr); // TODO: store the key type in a metadata + // table, not in the records' table; so + // it can be stored once only. // save the published nodes to the cache, to be later stored into the DB - /*unsigned int recordID = */addRecord(cachePublishedNodes, values); - //std::cout << "Pushed record: " << recordID << std::endl; // debug msg + /*unsigned int recordID = */ addRecord(cachePublishedNodes, values); + // std::cout << "Pushed record: " << recordID << std::endl; // debug msg } } /* -void WriteGeoModel::storeDataTable( std::string tableName, std::vector<std::string> colNames, std::vector<std::string> colTypes, std::vector<std::vector<std::string>> tableData ) +void WriteGeoModel::storeDataTable( std::string tableName, +std::vector<std::string> colNames, std::vector<std::string> colTypes, +std::vector<std::vector<std::string>> tableData ) { m_auxiliaryTablesStr[ tableName ] = std::make_pair(colNames, colTypes); m_auxiliaryTablesStrData[ tableName ] = tableData; } */ -void WriteGeoModel::storeDataTable( std::string tableName, std::vector<std::string> colNames, std::vector<std::string> colTypes, std::vector<std::vector<std::variant<int,long,float,double,std::string>>> tableData ) -{ - m_auxiliaryTablesVar[ tableName ] = std::make_pair(colNames, colTypes); - m_auxiliaryTablesVarData[ tableName ] = tableData; +void WriteGeoModel::storeDataTable( + std::string tableName, std::vector<std::string> colNames, + std::vector<std::string> colTypes, + std::vector< + std::vector<std::variant<int, long, float, double, std::string>>> + tableData) { + m_auxiliaryTablesVar[tableName] = std::make_pair(colNames, colTypes); + m_auxiliaryTablesVarData[tableName] = tableData; } - - - void WriteGeoModel::storeAddress(const std::string &address, const unsigned int &id) -{ - m_memMap.insert( std::pair<std::string,unsigned int>(address, id) ); +void WriteGeoModel::storeAddress(const std::string& address, + const unsigned int& id) { + m_memMap.insert(std::pair<std::string, unsigned int>(address, id)); } - bool WriteGeoModel::isAddressStored(const std::string &address) -{ - //showMemoryMap(); // only for Debug - std::unordered_map<std::string, unsigned int>::iterator it = m_memMap.find(address); - return ( it != m_memMap.end() ); +bool WriteGeoModel::isAddressStored(const std::string& address) { + // showMemoryMap(); // only for Debug + std::unordered_map<std::string, unsigned int>::iterator it = + m_memMap.find(address); + return (it != m_memMap.end()); } - - unsigned int WriteGeoModel::getStoredIdFromAddress(const std::string &address) -{ - return m_memMap.at(address); +unsigned int WriteGeoModel::getStoredIdFromAddress(const std::string& address) { + return m_memMap.at(address); } // get pointer string - std::string WriteGeoModel::getAddressStringFromPointer(const GeoMaterial* pointer) -{ - std::ostringstream oss; - oss << pointer; - return getQStringFromOss(oss); +std::string WriteGeoModel::getAddressStringFromPointer( + const GeoMaterial* pointer) { + std::ostringstream oss; + oss << pointer; + return getQStringFromOss(oss); } // get pointer string -std::string WriteGeoModel::getAddressStringFromPointer(const GeoElement* pointer) -{ - std::ostringstream oss; - oss << pointer; - return getQStringFromOss(oss); +std::string WriteGeoModel::getAddressStringFromPointer( + const GeoElement* pointer) { + std::ostringstream oss; + oss << pointer; + return getQStringFromOss(oss); } // get pointer string -std::string WriteGeoModel::getAddressStringFromPointer(const GeoShape* pointer) -{ - std::ostringstream oss; - oss << pointer; - return getQStringFromOss(oss); +std::string WriteGeoModel::getAddressStringFromPointer( + const GeoShape* pointer) { + std::ostringstream oss; + oss << pointer; + return getQStringFromOss(oss); } // get pointer string -std::string WriteGeoModel::getAddressStringFromPointer(const GeoLogVol* pointer) -{ - std::ostringstream oss; - oss << pointer; - return getQStringFromOss(oss); +std::string WriteGeoModel::getAddressStringFromPointer( + const GeoLogVol* pointer) { + std::ostringstream oss; + oss << pointer; + return getQStringFromOss(oss); } // get pointer string -std::string WriteGeoModel::getAddressStringFromPointer(const GeoPhysVol* pointer) -{ - std::ostringstream oss; - oss << pointer; - return getQStringFromOss(oss); -} -std::string WriteGeoModel::getAddressStringFromPointer(const GeoVPhysVol* pointer) -{ - std::ostringstream oss; - oss << pointer; - return getQStringFromOss(oss); +std::string WriteGeoModel::getAddressStringFromPointer( + const GeoPhysVol* pointer) { + std::ostringstream oss; + oss << pointer; + return getQStringFromOss(oss); +} +std::string WriteGeoModel::getAddressStringFromPointer( + const GeoVPhysVol* pointer) { + std::ostringstream oss; + oss << pointer; + return getQStringFromOss(oss); } // get pointer string -std::string WriteGeoModel::getAddressStringFromPointer(const GeoSerialDenominator* pointer) -{ - std::ostringstream oss; - oss << pointer; - return getQStringFromOss(oss); +std::string WriteGeoModel::getAddressStringFromPointer( + const GeoSerialDenominator* pointer) { + std::ostringstream oss; + oss << pointer; + return getQStringFromOss(oss); } -std::string WriteGeoModel::getAddressStringFromPointer(const GeoSerialIdentifier* pointer) -{ - std::ostringstream oss; - oss << pointer; - return getQStringFromOss(oss); +std::string WriteGeoModel::getAddressStringFromPointer( + const GeoSerialIdentifier* pointer) { + std::ostringstream oss; + oss << pointer; + return getQStringFromOss(oss); } -std::string WriteGeoModel::getAddressStringFromPointer(const GeoIdentifierTag* pointer) -{ - std::ostringstream oss; - oss << pointer; - return getQStringFromOss(oss); +std::string WriteGeoModel::getAddressStringFromPointer( + const GeoIdentifierTag* pointer) { + std::ostringstream oss; + oss << pointer; + return getQStringFromOss(oss); } -std::string WriteGeoModel::getAddressStringFromPointer(const GeoSerialTransformer* pointer) -{ - std::ostringstream oss; - oss << pointer; - return getQStringFromOss(oss); +std::string WriteGeoModel::getAddressStringFromPointer( + const GeoSerialTransformer* pointer) { + std::ostringstream oss; + oss << pointer; + return getQStringFromOss(oss); } -std::string WriteGeoModel::getAddressStringFromPointer(const GeoXF::Function* pointer) -{ - std::ostringstream oss; - oss << pointer; - return getQStringFromOss(oss); +std::string WriteGeoModel::getAddressStringFromPointer( + const GeoXF::Function* pointer) { + std::ostringstream oss; + oss << pointer; + return getQStringFromOss(oss); } -std::string WriteGeoModel::getAddressStringFromPointer(const GeoTransform* pointer) -{ - std::ostringstream oss; - oss << pointer; - return getQStringFromOss(oss); +std::string WriteGeoModel::getAddressStringFromPointer( + const GeoTransform* pointer) { + std::ostringstream oss; + oss << pointer; + return getQStringFromOss(oss); } -std::string WriteGeoModel::getAddressStringFromPointer(const GeoNameTag* pointer) -{ - std::ostringstream oss; - oss << pointer; - return getQStringFromOss(oss); +std::string WriteGeoModel::getAddressStringFromPointer( + const GeoNameTag* pointer) { + std::ostringstream oss; + oss << pointer; + return getQStringFromOss(oss); } -std::string WriteGeoModel::getQStringFromOss(std::ostringstream &oss) -{ - std::string addr = oss.str(); - return addr; +std::string WriteGeoModel::getQStringFromOss(std::ostringstream& oss) { + std::string addr = oss.str(); + return addr; } - } /* namespace GeoModelIO */ diff --git a/GeoModelIO/README.md b/GeoModelIO/README.md index a4ff7dc752b1131cc38704c301245ec8d13cb490..d0568be77f36be1ab4b3f3d21558ed539cc304a5 100644 --- a/GeoModelIO/README.md +++ b/GeoModelIO/README.md @@ -1,4 +1,4 @@ -[](https://gitlab.cern.ch/GeoModelDev/GeoModelIO/commits/master) +[](https://gitlab.cern.ch/GeoModelDev/GeoModelIO/commits/main) # GeoModelIO @@ -59,7 +59,7 @@ export GEOMODEL_ENV_IO_NTHREADS=-1 If you want to work on the library code, or if you want to use the latest version of the code, you have to build it by yourself. -First, install or build the [GeoModelCore](https://gitlab.cern.ch/GeoModelDev/GeoModelCore) dependency, by following [its instructions](https://gitlab.cern.ch/GeoModelDev/GeoModelCore/blob/master/README.md). +First, install or build the [GeoModelCore](https://gitlab.cern.ch/GeoModelDev/GeoModelCore) dependency, by following [its instructions](https://gitlab.cern.ch/GeoModelDev/GeoModelCore/blob/main/README.md). Then, get the code of this library and compile it: diff --git a/GeoModelTools/CMakeLists.txt b/GeoModelTools/CMakeLists.txt index 738f05fcc77372e932a93965af045e831acd1f24..bed80fb75f6f943b19353885f3239e9281857724 100644 --- a/GeoModelTools/CMakeLists.txt +++ b/GeoModelTools/CMakeLists.txt @@ -1,7 +1,7 @@ # Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration # CMake settings -cmake_minimum_required( VERSION 3.14 ) +cmake_minimum_required(VERSION 3.16...3.26) # Dummy call to 'project()', needed to set 'PROJECT_SOURCE_DIR' project( "GeoModelTools" ) @@ -27,17 +27,11 @@ if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) "Framework finding behaviour on macOS" ) # Set up how the project handle some of its dependenices. Either by picking them # up from the environment, or building them itself. - if( NOT TARGET JSONExt ) - include( SetupJSON ) - endif() - if( NOT TARGET XercesCBuiltIn ) - include( SetupXercesC ) - endif() + include( SetupJSON ) + include( SetupXercesC ) # Find the base GeoModel packages, which must be installed on the target system already find_package( GeoModelCore REQUIRED ${GeoModel_VERSION} ) find_package( GeoModelIO REQUIRED ${GeoModel_VERSION} ) - # Set a flag to steer the build of the subpackages - #set( VISUALIZATION_INDIVIDUAL_BUILD ON ) # Print Build Info on screen include( PrintBuildInfo ) else() @@ -59,6 +53,7 @@ add_subdirectory( ExpressionEvaluator ) add_subdirectory( GMCAT ) add_subdirectory( GMSTATISTICS ) add_subdirectory( GDMLtoGM ) +add_subdirectory( GeoModelValidation ) # Create and install the version description of the project. include( WriteBasicConfigVersionFile ) diff --git a/GeoModelTools/GDMLtoGM/CMakeLists.txt b/GeoModelTools/GDMLtoGM/CMakeLists.txt index 7b57447e2f0762924643acc92e139b67e66dfc92..16a10e98a3d781bfdc14440563a99f50c31f68c5 100644 --- a/GeoModelTools/GDMLtoGM/CMakeLists.txt +++ b/GeoModelTools/GDMLtoGM/CMakeLists.txt @@ -6,12 +6,6 @@ file( GLOB HEADERS GDMLInterface/*.h ) # Create the library. add_library( GDMLtoGM SHARED ${HEADERS} ${SOURCES} ) - -# If the in-house build of the Xerces-C library is used, add explicit dependency -if( GEOMODEL_USE_BUILTIN_XERCESC ) - add_dependencies( GDMLtoGM XercesCBuiltIn ) -endif() - target_link_libraries( GDMLtoGM PUBLIC XercesC::XercesC ExpressionEvaluator GeoModelXMLParser GeoModelCore::GeoModelKernel ) target_include_directories( GDMLtoGM PUBLIC diff --git a/GeoModelTools/GDMLtoGM/src/GDMLtoGM.cxx b/GeoModelTools/GDMLtoGM/src/GDMLtoGM.cxx index 4530b696d4113a92841a03f1b5e0fc90762737fb..e27c4ff5e68bddd59a1c11621b0058ecc454bc2f 100644 --- a/GeoModelTools/GDMLtoGM/src/GDMLtoGM.cxx +++ b/GeoModelTools/GDMLtoGM/src/GDMLtoGM.cxx @@ -31,7 +31,7 @@ class GDMLtoGM : public GeoVGeometryPlugin { ~GDMLtoGM(); // Creation of geometry: - virtual void create(GeoPhysVol *world, bool publish = false ) override; + virtual void create(GeoVPhysVol *world, bool publish = false ) override; private: @@ -48,7 +48,7 @@ GDMLtoGM::~GDMLtoGM() //## Other Operations (implementation) -void GDMLtoGM::create(GeoPhysVol *world, bool /* 'publish' is not used here */) +void GDMLtoGM::create(GeoVPhysVol *world, bool /* 'publish' is not used here */) { char* fPath=getenv("GDML_FILE_NAME"); std::string fileName; diff --git a/GeoModelTools/GMCAT/CMakeLists.txt b/GeoModelTools/GMCAT/CMakeLists.txt index 455027fc43799498bc86095beef6cc73a8495a22..b3a2ab02cd9aca6715254d346afe956fb9ea7f46 100644 --- a/GeoModelTools/GMCAT/CMakeLists.txt +++ b/GeoModelTools/GMCAT/CMakeLists.txt @@ -1,10 +1,12 @@ # Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration # Declare the package's executable. -add_executable( gmcat src/gmcat.cxx ) +add_executable( gmcat src/gmcat.cxx src/publishMetaData.cpp) target_link_libraries( gmcat PRIVATE GeoModelCore::GeoModelKernel - GeoModelIO::GeoModelRead GeoModelIO::GeoModelWrite - GeoModelIO::GeoModelDBManager ) + GeoModelCore::GeoModelFuncSnippets + GeoModelIO::GeoModelRead + GeoModelIO::GeoModelWrite + GeoModelIO::GeoModelDBManager ) # Tweak how debug information should be attached to the executable, in Debug # builds. @@ -12,6 +14,7 @@ if( "${CMAKE_BUILD_TYPE}" STREQUAL "Debug" AND "${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU" ) target_compile_options( gmcat PRIVATE "-gdwarf-2" ) endif() +target_compile_options( gmcat PRIVATE "-DGMVERSION=${GeoModel_VERSION}" ) # Install the executable. install( TARGETS gmcat diff --git a/GeoModelTools/GMCAT/src/gmcat.cxx b/GeoModelTools/GMCAT/src/gmcat.cxx index f2d37bbaa3224828b8298c78b6b88ad2773d51d7..467895fa269931040eb4759803a92fd7a9a17ee2 100644 --- a/GeoModelTools/GMCAT/src/gmcat.cxx +++ b/GeoModelTools/GMCAT/src/gmcat.cxx @@ -6,12 +6,13 @@ #include "GeoModelDBManager/GMDBManager.h" #include "GeoModelRead/ReadGeoModel.h" #include "GeoModelWrite/WriteGeoModel.h" +#include "GeoModelFuncSnippets/defineWorld.h" #include "GeoModelKernel/GeoGeometryPluginLoader.h" #include "GeoModelKernel/GeoVolumeCursor.h" #include "GeoModelKernel/GeoMaterial.h" #include "GeoModelKernel/GeoElement.h" -#include "GeoModelKernel/GeoPVLink.h" +#include "GeoModelKernel/GeoVPhysVol.h" #include "GeoModelKernel/GeoBox.h" #include "GeoModelKernel/GeoCountVolAction.h" #include "GeoModelKernel/GeoAccessVolumeAction.h" @@ -23,7 +24,7 @@ #include <vector> #include <cstdio> #include <unistd.h> -#include <stdlib.h> // setenv +#include <stdlib.h> #ifdef __APPLE__ const std::string shared_obj_extension=".dylib"; @@ -31,45 +32,16 @@ const std::string shared_obj_extension=".dylib"; const std::string shared_obj_extension=".so"; #endif -#define SYSTEM_OF_UNITS GeoModelKernelUnits // --> 'GeoModelKernelUnits::cm' -int main(int argc, char ** argv) { +void publishMetaData( GMDBManager & db, + std::vector<std::string> &inputFiles, + std::vector<std::string> &inputPlugins, + std::string &outputFile); +int main(int argc, char ** argv) { - struct Metadata { - std::string dateString; - std::string geoModelDataBranch; - } metadata; - // Fill metadata; - { - // Ceci n'es pas une pipe: - FILE *ceci=popen("date -Im","r"); - if (ceci) { - char buff[1024]; - if (fscanf(ceci,"%s",buff)) { - metadata.dateString=buff; - } - pclose(ceci); - } - } - - char *geomodel_xml_dir=getenv("GEOMODEL_XML_DIR"); - if (geomodel_xml_dir) { - std::string cmd="git -C "+ std::string(geomodel_xml_dir) + " rev-parse --abbrev-ref HEAD"; - // Ceci n'es pas une pipe: - FILE *ceci=popen(cmd.c_str(),"r"); - if (ceci) { - char buff[1024]; - if (fscanf(ceci,"%s",buff)) { - metadata.geoModelDataBranch=buff; - } - pclose(ceci); - } - } - - // // Usage message: // @@ -143,35 +115,11 @@ int main(int argc, char ** argv) { // - // Create elements and materials for the "World" volume, which is the container: - // - - const double gr = SYSTEM_OF_UNITS::gram; - const double mole = SYSTEM_OF_UNITS::mole; - const double cm3 = SYSTEM_OF_UNITS::cm3; - - // Define the chemical elements - GeoElement* Nitrogen = new GeoElement ("Nitrogen" ,"N" , 7.0 , 14.0067 *gr/mole); - GeoElement* Oxygen = new GeoElement ("Oxygen" ,"O" , 8.0 , 15.9995 *gr/mole); - GeoElement* Argon = new GeoElement ("Argon" ,"Ar" , 18.0 , 39.948 *gr/mole); - GeoElement* Hydrogen = new GeoElement ("Hydrogen" ,"H" , 1.0 , 1.00797 *gr/mole); - - double densityOfAir=0.001214 *gr/cm3; - GeoMaterial *air = new GeoMaterial("Air", densityOfAir); - air->add(Nitrogen , 0.7494); - air->add(Oxygen, 0.2369); - air->add(Argon, 0.0129); - air->add(Hydrogen, 0.0008); - air->lock(); - - // - // Create a huge world volume made of Air: + // Create the "GeoWorld" volume, which is the container: // + GeoIntrusivePtr<GeoPhysVol> world{createGeoWorld()}; + - const GeoBox* worldBox = new GeoBox(2000*SYSTEM_OF_UNITS::cm, 2000*SYSTEM_OF_UNITS::cm, 2500*SYSTEM_OF_UNITS::cm); - const GeoLogVol* worldLog = new GeoLogVol("WorldLog", worldBox, air); - GeoPhysVol *world=new GeoPhysVol(worldLog); - world->ref(); // // Loop over plugins, create the geometry and put it under the world: // @@ -210,7 +158,7 @@ int main(int argc, char ** argv) { GeoModelIO::ReadGeoModel readInGeo = GeoModelIO::ReadGeoModel(db); /* build the GeoModel geometry */ - GeoPhysVol* dbPhys = readInGeo.buildGeoModel(); // builds the whole GeoModel tree in memory + const GeoVPhysVol* dbPhys = readInGeo.buildGeoModel(); // builds the whole GeoModel tree in memory /* get an handle on a Volume Cursor, to traverse the whole set of Volumes */ GeoVolumeCursor aV(dbPhys); @@ -241,26 +189,21 @@ int main(int argc, char ** argv) { std::cerr << "gmcat -- Error opening the output file: " << outputFile << std::endl; return 7; } - // - // Fill the header file with metadata - // - std::vector<std::string> gmcatColNames={"Date", "GeoModelDataBranch"}; - std::vector<std::string> gmcatColTypes={"STRING", "STRING" }; - std::vector<std::vector<std::variant<int,long,float,double,std::string>>> gmcatData ={{metadata.dateString, metadata.geoModelDataBranch}}; - - db.createCustomTable("AAHEADER", gmcatColNames,gmcatColTypes,gmcatData); - GeoModelIO::WriteGeoModel dumpGeoModelGraph(db); - world->exec(&dumpGeoModelGraph); + + //resize the world volume to the needed one + GeoIntrusivePtr<GeoPhysVol> resizedWorld = resizeGeoWorld(world); + GeoModelIO::WriteGeoModel dumpGeoModelGraph(db); + resizedWorld->exec(&dumpGeoModelGraph); if (vecPluginsPublishers.size() > 0) { - dumpGeoModelGraph.saveToDB(vecPluginsPublishers); + dumpGeoModelGraph.saveToDB(vecPluginsPublishers); } else { - dumpGeoModelGraph.saveToDB(); + dumpGeoModelGraph.saveToDB(); } - world->unref(); - + publishMetaData(db,inputFiles,inputPlugins,outputFile); + return 0; } diff --git a/GeoModelTools/GMCAT/src/publishMetaData.cpp b/GeoModelTools/GMCAT/src/publishMetaData.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f06210c29c5d6a0ea99b8e3cb61a149e66ea8e04 --- /dev/null +++ b/GeoModelTools/GMCAT/src/publishMetaData.cpp @@ -0,0 +1,226 @@ +#include "GeoModelDBManager/GMDBManager.h" +#include <string> +#include <iostream> +#include <unistd.h> +#include <cstdio> +#include <vector> +#include <algorithm> +#include <sys/utsname.h> +#include <array> +#define STR_VALUE(arg) #arg +#define STR_NAME(name) STR_VALUE(name) + +std::string resolveVariable(const std::string& varName) { + const char* var = std::getenv(varName.c_str()); + if (!var) return std::string{}; + return std::string(var); +} +std::string getCommandOutput(const std::string & cmd, bool firstLineOnly=false) +{ + std::string response; + // Ceci n'est pas une pipe: + FILE *ceci=popen(cmd.c_str(),"r"); + if (ceci) { + static const int MSGSIZE=1024; + std::array<char, 1024> buff{}; + while (fgets(buff.data(),MSGSIZE,ceci)!=NULL) { + response+=std::string(buff.data()); + if (firstLineOnly) break; + } + pclose(ceci); + } + return response; +} + +void publishMetaData( GMDBManager & db, + std::vector<std::string> &inputFiles, + std::vector<std::string> &inputPlugins, + std::string &outputFile) { + + struct Metadata { + std::string dateString=getCommandOutput("date -Iminutes"); + std::string username{resolveVariable("USER")}; + std::string hostname{}; + std::string os; + std::string wd; + std::string gmversion=STR_NAME(GMVERSION); + std::string outputFile; + std::string geoModelDataBranch="Undefined"; // or overwritten below + std::string gmdataIsClean ="Not applicable"; // or overwritten below + std::string gmdataCommitHash ="Undefined"; // or overwritten below + std::string gmdataAssociatedTag = "Undefined"; // or overwritten below + } metadata; + + struct XtraMetadata { + std::string repo ="Undefined"; // or overwritten below + std::string branch ="Undefined"; // or overwritten below + std::string isClean ="Not applicable"; // or overwritten below + std::string commitHash ="Undefined"; // or overwritten below + std::string associatedTag ="Undefined"; // or overwritten below + } xtraMetadata; + +#ifdef __APPLE__ + char wdbuff[1024]; + metadata.wd=std::string(getcwd(wdbuff,1024)); +#else + metadata.wd= resolveVariable("PWD"); +#endif + + metadata.outputFile=outputFile; + utsname uts; + uname (&uts); + metadata.os=std::string(uts.sysname)+ "-" + std::string(uts.machine); + + // Sometimes "HOSTNAME" is empty as seen from gmcat. + if (metadata.hostname.empty()) { + char hn[1024]; + if (gethostname (hn,1024)==0) metadata.hostname=std::string(hn); + } + + std::string geomodel_xml_dir=resolveVariable("GEOMODEL_XML_DIR"); + if (!geomodel_xml_dir.empty()) { + { + metadata.geoModelDataBranch=getCommandOutput("git -C "+ geomodel_xml_dir + " rev-parse --abbrev-ref HEAD"); + std::string shortGitStatus=getCommandOutput("git -C "+ geomodel_xml_dir + " status -s "); + if (shortGitStatus!="") { + metadata.gmdataIsClean="no"; + } + else { + std::string synchedToOrigin=getCommandOutput("git -C "+ std::string(geomodel_xml_dir) + " diff origin/"+metadata.geoModelDataBranch,true); + if (synchedToOrigin!="") { + metadata.gmdataIsClean="no"; + } + else { + metadata.gmdataIsClean="yes"; + metadata.gmdataCommitHash=getCommandOutput("git -C " + std::string(geomodel_xml_dir) + " log -1 --format=format:\"%H\""); + metadata.gmdataAssociatedTag=getCommandOutput("git -C " + std::string(geomodel_xml_dir) + " describe --tag " + metadata.gmdataCommitHash+ " 2> /dev/null"); + } + } + } + } + std::string isGitManaged=getCommandOutput("git rev-parse --is-inside-work-tree"); + if (isGitManaged=="true\n") { + xtraMetadata.repo=getCommandOutput("git remote get-url origin"); + xtraMetadata.branch=getCommandOutput("git rev-parse --abbrev-ref HEAD"); + std::string status=getCommandOutput("git status --porcelain"); + if (status.find(" M ")!=std::string::npos) { + xtraMetadata.isClean="no"; + } + else { + std::string synchedToOrigin=getCommandOutput("git diff origin/"+xtraMetadata.branch,true); + if (synchedToOrigin!="") { + xtraMetadata.isClean="no"; + } + else { + xtraMetadata.isClean="yes"; + xtraMetadata.commitHash=getCommandOutput("git log -1 --format=format:\"%H\""); + xtraMetadata.associatedTag=getCommandOutput("git describe --tag " + xtraMetadata.commitHash+ " 2> /dev/null"); + } + } + } + + // + // Fill the header file with metadata + // + std::vector<std::string> gmcatColNames={"Date", + "GeoModelDataBranch", + "Username", + "Hostname", + "OS", + "WorkingDirectory", + "GeoModelVersion", + "OutputFile", + "GeoModelDataIsClean", + "GeoModelDataCommitHash", + "GeoModelDataAssociatedTag" + }; + std::vector<std::string> gmcatColTypes={"STRING", + "STRING" , + "STRING", + "STRING", + "STRING", + "STRING", + "STRING", + "STRING", + "STRING", + "STRING", + "STRING" + }; + + // Strip extraneous \n + for (std::string * s : { + &metadata.geoModelDataBranch, + &metadata.dateString, + &metadata.gmdataAssociatedTag}) { + s->erase(std::remove(s->begin(), s->end(), '\n'), s->end()); + std::cout << s << std::endl; + } + + + + std::vector<std::vector<std::variant<int,long,float,double,std::string>>> gmcatData ={{ + metadata.dateString, + metadata.geoModelDataBranch, + metadata.username, + metadata.hostname, + metadata.os, + metadata.wd, + metadata.gmversion, + metadata.outputFile, + metadata.gmdataIsClean, + metadata.gmdataCommitHash, + metadata.gmdataAssociatedTag + }}; + + unsigned int pcounter(0); + for (std::string plugin : inputPlugins) { + gmcatColNames.push_back("P"+std::to_string(pcounter++)); + gmcatColTypes.push_back("STRING"); + gmcatData[0].push_back((plugin)); + } + unsigned int fcounter(0); + for (std::string file : inputFiles) { + gmcatColNames.push_back("F"+std::to_string(fcounter++)); + gmcatColTypes.push_back("STRING"); + gmcatData[0].push_back(file); + } + + // Strip extraneous \n + for (std::string * s : { + &xtraMetadata.repo, + &xtraMetadata.branch }) { + s->erase(std::remove(s->begin(), s->end(), '\n'), s->end()); + std::cout << s << std::endl; + } + + + + if (xtraMetadata.branch!="Undefined") { + std::vector<std::string> xtraColNames={ + "UserCodeGitRepository", + "UserCodeGitBranch", + "UserCodeRepoIsClean", + "UserCodeRepoCommitHash", + "UserCodeAssociatedTag"}; + std::vector<std::string> xtraColTypes={"STRING", + "STRING", + "STRING", + "STRING", + "STRING"}; + std::vector<std::vector<std::variant<int,long,float,double,std::string>>> xtraData ={{ + xtraMetadata.repo, + xtraMetadata.branch, + xtraMetadata.isClean, + xtraMetadata.commitHash, + xtraMetadata.associatedTag + }}; + using std::begin, std::end; + gmcatColNames.insert(end(gmcatColNames), begin(xtraColNames), end(xtraColNames)); + gmcatColTypes.insert(end(gmcatColTypes), begin(xtraColTypes), end(xtraColTypes)); + gmcatData[0].insert(end(gmcatData[0]), begin(xtraData[0]), end(xtraData[0])); + db.createCustomTable("AAHEADER", gmcatColNames,gmcatColTypes,gmcatData); + } + else { + db.createCustomTable("AAHEADER", gmcatColNames,gmcatColTypes,gmcatData); + } +} diff --git a/GeoModelTools/GMSTATISTICS/CMakeLists.txt b/GeoModelTools/GMSTATISTICS/CMakeLists.txt index 4a34fa2fb976749a23360eec3d434d9fdbaf7499..854b50f3ad6a6b929003510977d2bdc631ad7cd5 100644 --- a/GeoModelTools/GMSTATISTICS/CMakeLists.txt +++ b/GeoModelTools/GMSTATISTICS/CMakeLists.txt @@ -3,8 +3,10 @@ # Declare the package's executable. add_executable( gmstatistics src/gmstatistics.cxx src/GeoInventoryGraphAction.cxx ) target_link_libraries( gmstatistics PRIVATE GeoModelCore::GeoModelKernel - GeoModelIO::GeoModelRead GeoModelIO::GeoModelWrite - GeoModelIO::GeoModelDBManager ) + GeoModelIO::GeoModelRead + GeoModelIO::GeoModelWrite + GeoModelIO::GeoModelDBManager + GeoModelCore::GeoModelFuncSnippets ) # Tweak how debug information should be attached to the executable, in Debug # builds. diff --git a/GeoModelTools/GMSTATISTICS/src/gmstatistics.cxx b/GeoModelTools/GMSTATISTICS/src/gmstatistics.cxx index 551738da65077dd6c440ed4ef6c3e381e7fc9f17..ac66b4f2d314f15b65f1173a20ee737953a90f92 100644 --- a/GeoModelTools/GMSTATISTICS/src/gmstatistics.cxx +++ b/GeoModelTools/GMSTATISTICS/src/gmstatistics.cxx @@ -7,11 +7,11 @@ #include "GeoModelKernel/GeoVolumeCursor.h" #include "GeoModelKernel/GeoMaterial.h" #include "GeoModelKernel/GeoElement.h" -#include "GeoModelKernel/GeoPVLink.h" #include "GeoModelKernel/GeoBox.h" #include "GeoModelKernel/GeoCountVolAction.h" #include "GeoModelKernel/GeoAccessVolumeAction.h" #include "GeoModelKernel/GeoNameTag.h" +#include "GeoModelFuncSnippets/defineWorld.h" #include "GeoInventoryGraphAction.h" #include <fstream> #include <iostream> @@ -44,7 +44,6 @@ const std::string shared_obj_extension=".so"; double factor=1000.0; #endif -#define SYSTEM_OF_UNITS GeoModelKernelUnits // --> 'GeoModelKernelUnits::cm' int snoop() { struct rusage usage; @@ -100,37 +99,7 @@ int main(int argc, char ** argv) { for (const std::string & plugin : inputPlugins) { - - // - // Create elements and materials: - // - - const double gr = SYSTEM_OF_UNITS::gram; - const double mole = SYSTEM_OF_UNITS::mole; - const double cm3 = SYSTEM_OF_UNITS::cm3; - - // Define the chemical elements - GeoElement* Nitrogen = new GeoElement ("Nitrogen" ,"N" , 7.0 , 14.0067 *gr/mole); - GeoElement* Oxygen = new GeoElement ("Oxygen" ,"O" , 8.0 , 15.9995 *gr/mole); - GeoElement* Argon = new GeoElement ("Argon" ,"Ar" , 18.0 , 39.948 *gr/mole); - GeoElement* Hydrogen = new GeoElement ("Hydrogen" ,"H" , 1.0 , 1.00797 *gr/mole); - - double densityOfAir=0.001214 *gr/cm3; - GeoMaterial *air = new GeoMaterial("Air", densityOfAir); - air->add(Nitrogen , 0.7494); - air->add(Oxygen, 0.2369); - air->add(Argon, 0.0129); - air->add(Hydrogen, 0.0008); - air->lock(); - - // - // Create a huge world volume made of Air: - // - - const GeoBox* worldBox = new GeoBox(2000*SYSTEM_OF_UNITS::cm, 2000*SYSTEM_OF_UNITS::cm, 2500*SYSTEM_OF_UNITS::cm); - const GeoLogVol* worldLog = new GeoLogVol("WorldLog", worldBox, air); - GeoPhysVol *world=new GeoPhysVol(worldLog); - world->ref(); + GeoIntrusivePtr<GeoPhysVol> world{createGeoWorld()}; // // Loop over plugins, create the geometry and put it under the world: // diff --git a/GeoModelTools/GeoModelJSONParser/CMakeLists.txt b/GeoModelTools/GeoModelJSONParser/CMakeLists.txt index 28eb7d0f8adfd8dc1e1e61d739ba9c8134d1ec6b..2e3f980ab55cfab57ad98d5eb2ed18ccb248d144 100644 --- a/GeoModelTools/GeoModelJSONParser/CMakeLists.txt +++ b/GeoModelTools/GeoModelJSONParser/CMakeLists.txt @@ -6,20 +6,7 @@ file( GLOB HEADERS GeoModelJSONParser/*.h ) # Create the library. add_library( GeoModelJSONParser SHARED ${HEADERS} ${SOURCES} ) - -# If the in-house build of the nlohmann_json library is used, add explicit dependency -if( GEOMODEL_USE_BUILTIN_JSON ) - add_dependencies( GeoModelJSONParser JSONExt ) -endif() - -# We link to `nlohmann_json` only if we use a version of nlohmann_json -# that provides a CMake config file (i.e., either built from source, or also -# installed with Homebrew on macOS). -# This is not needed if the single-header library is installed in a regular -# system include folder (e.g., '/usr/local/include', '/usr/include', ...) -if ( nlohmann_json_FOUND ) - target_link_libraries( GeoModelJSONParser PUBLIC nlohmann_json::nlohmann_json ) -endif() +target_link_libraries( GeoModelJSONParser PUBLIC nlohmann_json::nlohmann_json ) target_include_directories( GeoModelJSONParser PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> diff --git a/GeoModelTools/GeoModelValidation/CMakeLists.txt b/GeoModelTools/GeoModelValidation/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..87f9d75fae07498828b32ba1c7446586956b7254 --- /dev/null +++ b/GeoModelTools/GeoModelValidation/CMakeLists.txt @@ -0,0 +1,42 @@ +# Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration + +# Find the header and source files. +file( GLOB SOURCES src/*.cxx ) +file( GLOB HEADERS GeoModelValidation/*.h ) + +#find_package( GeoModelUtilities REQUIRED ) + +# Create the library. +add_library( GeoModelValidation SHARED ${HEADERS} ${SOURCES} ) +target_link_libraries( GeoModelValidation PUBLIC Eigen3::Eigen GeoModelCore::GeoGenericFunctions GeoModelCore::GeoModelKernel GeoModelIO::GeoModelDBManager GeoModelIO::GeoModelWrite GeoModelIO::GeoModelRead ) +target_include_directories( GeoModelValidation PUBLIC + $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> + $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> ) +source_group( "GeoModelValidation" FILES ${HEADERS} ) +source_group( "src" FILES ${SOURCES} ) +set_target_properties( GeoModelValidation PROPERTIES + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR} ) + +# Set up an alias with the same name that you would get by "finding" a pre-built +# version of the library. +add_library( GeoModelTools::GeoModelValidation ALIAS GeoModelValidation ) + +# Install the library. +install(TARGETS GeoModelValidation + EXPORT ${PROJECT_NAME}-export + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + COMPONENT Runtime + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT Runtime + NAMELINK_COMPONENT Development # Requires CMake 3.12 + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT Development + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/GeoModelValidation + COMPONENT Development + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} +) + +install( FILES ${HEADERS} + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/GeoModelValidation + COMPONENT Development ) diff --git a/GeoModelTools/GeoModelValidation/GeoModelValidation/GeoMaterialHelper.h b/GeoModelTools/GeoModelValidation/GeoModelValidation/GeoMaterialHelper.h new file mode 100755 index 0000000000000000000000000000000000000000..a6674d4f25024b075bf8a577e858916fa5ad730b --- /dev/null +++ b/GeoModelTools/GeoModelValidation/GeoModelValidation/GeoMaterialHelper.h @@ -0,0 +1,57 @@ +/* + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration +*/ + +/////////////////////////////////////////////////////////////////// +// GeoMaterialHelper.h, (c) ATLAS Detector software +/////////////////////////////////////////////////////////////////// + +#ifndef GEOMATERIALHELPER_H +#define GEOMATERIALHELPER_H + +#include <GeoModelKernel/GeoDefinitions.h> + +class GeoMaterial; +class GeoVPhysVol; + +namespace GeoModelTools { + + /** + @class GeoMaterialHelper + + A helper class that browses the GeoModel tree for material estimates + + @author sarka.todorova@cern.ch + */ + + typedef std::pair< const GeoMaterial*, double > MaterialComponent; + + class GeoMaterialHelper { + + public: + /** Default constructor*/ + GeoMaterialHelper() + {} + + /** Destructor*/ + virtual ~GeoMaterialHelper(){} + + /** Evaluate mass ( of a GeoModel tree/branch/volume ) */ + float evaluateMass(const GeoVPhysVol* gv, bool inclusive = true) const; + + /** Collect and blend material : return blended material (the client takes the ownership) and effective volume */ + MaterialComponent collectMaterial(const GeoVPhysVol* gv) const; + + /** hardcoded dummy materials : TODO : find generic criterium ( density ? radiation length ? ) */ + bool dummy_material(const GeoVPhysVol*) const; + + private: + /** Internal recursive loop over material components */ + void collectMaterialContent( const GeoVPhysVol* gv, std::vector< MaterialComponent >& materialContent ) const; + }; + + +} // end of namespace GeoModelTools + +#endif + diff --git a/GeoModelTools/GeoModelValidation/GeoModelValidation/GeoPhysVolHelper.h b/GeoModelTools/GeoModelValidation/GeoModelValidation/GeoPhysVolHelper.h new file mode 100755 index 0000000000000000000000000000000000000000..986b0e1c63309daf00521129adae284cae194db3 --- /dev/null +++ b/GeoModelTools/GeoModelValidation/GeoModelValidation/GeoPhysVolHelper.h @@ -0,0 +1,106 @@ +/* + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration +*/ + +/////////////////////////////////////////////////////////////////// +// GeoPhysVolHelper.h, (c) ATLAS Detector software +/////////////////////////////////////////////////////////////////// + +#ifndef GEOPHYSVOLHELPER_H +#define GEOPHYSVOLHELPER_H + +#include <GeoModelKernel/GeoDefinitions.h> +#include <vector> + +class GeoVPhysVol; +class GeoPhysVol; +class GeoShape; + +namespace GeoModelTools { // TODO resolve prototype/clone, identification scheme + + struct GM_valid{ + const GeoVPhysVol* test_branch; + const GeoVPhysVol* ref_branch; + int valid_strategy; + int valid_position; + int valid_branch; + + GM_valid(const GeoVPhysVol* testvol, const GeoVPhysVol* refvol, unsigned int strategy, int code_pos, int code_branch ) : + test_branch(testvol), ref_branch(refvol), valid_strategy(strategy), valid_position(code_pos), valid_branch(code_branch){} + }; + + /** + @class GeoPhysVolHelper + + A helper class that browses the GeoModel tree for validation purposes + + @author sarka.todorova@cern.ch + */ + + class GeoPhysVolHelper { + + public: + /** Default constructor*/ + GeoPhysVolHelper() + {} + + /** Destructor*/ + virtual ~GeoPhysVolHelper(){} + + /** Recursive comparison of trees/branches/volumes : + in quiet mode (printFullInfo=False) , returns the indicator of first encountered difference ( 0 if none), + in verbose mode (printFullInfo=True), returns the indicator of last encountered difference ( 0 if none) */ + int compareGeoVolumes( const GeoVPhysVol* gv1, const GeoVPhysVol* gv2, float tolerance, bool printFullInfo = false, int level=0 , int returnCode=0); + + /** Comparison of databases via sequential deployment of validation strategies to resolve modified tree hierarchy; + naming change resolved for alignable(sensitive) branches; + if no input branch name given, the comparison starts at the top level */ + void compareDB( std::string dbref_path, std::string dbtest_path, std::string branch_ref= "", std::string branch_test = "", bool printFullInfo = false, float tolerance = 1.e-4); + + /** Comparison of transforms : returns 0 code for identity, 6 for shift, 7 for change of orientation */ + int compareTransforms(GeoTrf::Transform3D trtest, GeoTrf::Transform3D trref, float tolerance) const; + + /** save tree/branch/volume into sqlite database file : to be replaced by GMIO.h */ + void saveToDb( const GeoVPhysVol* gv, std::string filename, bool silentMode=false); + + /** retrieve tree/branch/volume from sqlite database file : to be replaced by GMIO.h */ + const GeoVPhysVol* retrieveFromDb( std::string filename) const; + + /** shape comparison */ + bool compareShapes( const GeoShape* gs1, const GeoShape* gv2, float tolerance ) const; + + /** navigation through logical volumes */ + const GeoVPhysVol* findBranch( const GeoVPhysVol* top, std::string name, bool fullName=true, int searchDepth=-1 ) const; + const GeoVPhysVol* findAlignableBranch( const GeoVPhysVol* top, std::string name, GeoTrf::Transform3D transf, bool fullName=true, int searchDepth=-1 ) const; + + /** define partial name */ + void set_partial_name(unsigned int i0, unsigned int len) { + m_pnami = i0; m_pnaml = len; + } + + /** define output directory */ + void set_path_for_dump_diff( std::string path) { m_dump_diff_path = path; } + + /** dumps from GeoModel tree for debugging */ + void printInfo(const GeoVPhysVol* pv, int historyDepth=-1) const; + void printChildren(const GeoVPhysVol* pv, int level, int historyDepth) const; + void decodeShape(const GeoShape* sh) const; + + private: + mutable int m_diff; + mutable std::vector< GM_valid > m_test2db; + mutable std::vector< GM_valid > m_db2test; + unsigned int m_pnami = 0; + unsigned int m_pnaml = 2; + std::string m_dump_diff_path = ""; + /** check of rotation invariance */ + bool identity_check(GeoTrf::RotationMatrix3D rotation, float tol) const; + /** printout diff - unify output */ + void printTranslationDiff(GeoTrf::Transform3D trtest, GeoTrf::Transform3D trref, float tolerance) const; + void printRotationDiff(GeoTrf::Transform3D trtest, GeoTrf::Transform3D trref, float tolerance) const; + }; + +} // end of namespace GeoModelTools + +#endif + diff --git a/GeoModelTools/GeoModelValidation/src/GeoMaterialHelper.cxx b/GeoModelTools/GeoModelValidation/src/GeoMaterialHelper.cxx new file mode 100755 index 0000000000000000000000000000000000000000..a2e29c867bf03ba61c5b8549f7a1b72deb9ae4a5 --- /dev/null +++ b/GeoModelTools/GeoModelValidation/src/GeoMaterialHelper.cxx @@ -0,0 +1,115 @@ +/* + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration +*/ + +/////////////////////////////////////////////////////////////////// +// GeoMaterialHelper.cxx, (c) ATLAS Detector software +/////////////////////////////////////////////////////////////////// + +#include "GeoModelValidation/GeoMaterialHelper.h" + +// GeoModelKernel +#include "GeoModelKernel/GeoMaterial.h" +#include "GeoModelKernel/GeoElement.h" +#include "GeoModelKernel/Units.h" +#include "GeoModelKernel/GeoPhysVol.h" + +#include <string> + +float GeoModelTools::GeoMaterialHelper::evaluateMass( const GeoVPhysVol* gv, bool inclusive) const { + + const GeoLogVol* lv = gv->getLogVol(); + + float weight = 0.; + + double motherVolume = 0.; + + // skip volume calculation for dummy material configuration + if ( !this->dummy_material(gv) ) motherVolume = lv->getShape()->volume(); + + // subtract children volumes + //GeoVolumeVec_t vols = geoGetVolumes(gv); + //for (const GeoVolumeVec_t::value_type& p : vols) { + unsigned int nc = gv->getNChildVols(); + for (unsigned int ic = 0; ic < nc; ic++) { + const GeoVPhysVol* cv = &(*(gv->getChildVol(ic))); + double childVolume = cv->getLogVol()->getShape()->volume() ; + // skip volume calculation for dummy material configuration + if (!this->dummy_material(gv) ) motherVolume -= childVolume; // child volumes fully confined by construction + if (inclusive) weight += evaluateMass(cv, inclusive); + } + + // skip mass calculation for dummy material configuration + if (!this->dummy_material(gv)) weight += motherVolume * lv->getMaterial()->getDensity(); + + return weight; + +} + +GeoModelTools::MaterialComponent GeoModelTools::GeoMaterialHelper::collectMaterial( const GeoVPhysVol* gv) const { + + // iterative loop over substructure + std::vector< GeoModelTools::MaterialComponent > materialContent ; + collectMaterialContent( gv, materialContent ); + + // material blending + double volume = 0.; + double mass = 0.; + for ( auto matInput : materialContent ) { + volume += matInput.second; + mass += matInput.first->getDensity() * matInput.second; + } + + GeoMaterial* gmMatTmp=new GeoMaterial("MaterialBlend", mass / volume); + for ( auto matInput : materialContent ) { + gmMatTmp->add( matInput.first, matInput.first->getDensity() * matInput.second / mass ); + } + + gmMatTmp->lock(); + + return std::pair< const GeoMaterial*, double > ( gmMatTmp, volume ); + +} + +void GeoModelTools::GeoMaterialHelper::collectMaterialContent( const GeoVPhysVol* gv, std::vector< GeoModelTools::MaterialComponent >& materialContent ) const { + + const GeoLogVol* lv = gv->getLogVol(); + + double motherVolume = 0.; + + // skip volume calculation for dummy material configuration + if (!this->dummy_material(gv) ) motherVolume = lv->getShape()->volume(); + + // subtract children volumes from mother volume & collect their material content + //GeoVolumeVec_t vols = geoGetVolumes(gv); + //for (const GeoVolumeVec_t::value_type& p : vols) { + unsigned int nc = gv->getNChildVols(); + for (unsigned int ic = 0; ic < nc; ic++) { + const GeoVPhysVol* cv = &(*(gv->getChildVol(ic))); + double childVolume = cv->getLogVol()->getShape()->volume() ; + // skip for dummy material configuration + if (!this->dummy_material(gv) ) motherVolume -= childVolume; // child volumes fully confined by construction + collectMaterialContent( cv, materialContent ); + } + + // skip for dummy material configuration + if (!this->dummy_material(gv) ) materialContent.push_back( std::pair<const GeoMaterial*, double> ( lv->getMaterial(), motherVolume ) ); + + return; + +} + +bool GeoModelTools::GeoMaterialHelper::dummy_material(const GeoVPhysVol* vol) const { + + bool dummyMat = false; + + std::string mat = vol->getLogVol()->getMaterial()->getName(); + + if ( mat=="special::Ether" ) dummyMat = true; + if ( mat=="WorldLog:Air" ) dummyMat = true; + if ( mat=="std::Air" ) dummyMat = true; + if ( mat=="Air" ) dummyMat = true; + + return dummyMat; +} + diff --git a/GeoModelTools/GeoModelValidation/src/GeoPhysVolHelper.cxx b/GeoModelTools/GeoModelValidation/src/GeoPhysVolHelper.cxx new file mode 100755 index 0000000000000000000000000000000000000000..bf4a04b8973fed8ff64ebc19057dc28828bbc074 --- /dev/null +++ b/GeoModelTools/GeoModelValidation/src/GeoPhysVolHelper.cxx @@ -0,0 +1,804 @@ +/* + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration +*/ + +/////////////////////////////////////////////////////////////////// +// GeoPhysVolHelper.cxx, (c) ATLAS Detector software +/////////////////////////////////////////////////////////////////// + +#include "GeoModelValidation/GeoPhysVolHelper.h" +#include "GeoModelValidation/GeoMaterialHelper.h" + +// GeoModelKernel +#include "GeoModelKernel/GeoMaterial.h" +#include "GeoModelKernel/GeoElement.h" +#include "GeoModelKernel/Units.h" +#include "GeoModelKernel/GeoPhysVol.h" +///#include "GeoModelUtilities/GeoVisitVolumes.h" +#include "GeoModelDBManager/GMDBManager.h" +#include "GeoModelWrite/WriteGeoModel.h" +#include "GeoModelRead/ReadGeoModel.h" +#include "GeoModelKernel/GeoShape.h" +#include "GeoModelKernel/GeoShapeShift.h" +#include "GeoModelKernel/GeoShapeSubtraction.h" +#include "GeoModelKernel/GeoShapeUnion.h" +#include "GeoModelKernel/GeoShapeIntersection.h" +#include "GeoModelKernel/GeoTubs.h" +#include "GeoModelKernel/GeoTube.h" +#include "GeoModelKernel/GeoPcon.h" +#include "GeoModelKernel/GeoBox.h" +#include "GeoModelKernel/GeoCons.h" +#include "GeoModelKernel/GeoSimplePolygonBrep.h" +#include "GeoModelKernel/GeoTrd.h" +#include "GeoModelKernel/GeoTrap.h" +#include "GeoModelKernel/GeoPgon.h" +#include "GeoModelKernel/GeoPara.h" + +#include "GeoModelKernel/Units.h" +#define SYSTEM_OF_UNITS GeoModelKernelUnits + +#include <string> +#include <iostream> +#include <fstream> +#include <iomanip> + +void GeoModelTools::GeoPhysVolHelper::compareDB( std::string dbref_path, std::string dbtest_path, std::string branch_ref, std::string branch_test, bool printFullInfo, float tolerance) { + + const GeoVPhysVol* db_ref = this->retrieveFromDb(dbref_path); + const GeoVPhysVol* db_test = this->retrieveFromDb(dbtest_path); + + if (!db_ref) std::cout << "invalid input file "<<dbref_path<<", reference db not retrieved, exiting" << std::endl; + if (!db_test) std::cout << "invalid input file "<<dbtest_path<<", test db not retrieved, exiting" << std::endl; + + const GeoVPhysVol* top_ref = branch_ref!="" ? findBranch(db_ref, branch_ref) : db_ref; + const GeoVPhysVol* top_test = db_test; + if ( branch_test!="" ) top_test = findBranch(db_test, branch_test); + else if ( branch_ref!="" ) top_test = findBranch(db_test, branch_ref); + + if (!top_ref) { + std::cout << "required ref branch not found "<<branch_ref<<", trying to resolve from top" << std::endl; + top_ref = db_ref; + } + if (!top_test) { + std::cout << "required test branch not found "<<branch_test<<"/"<<branch_ref<<", trying to resolve from top" << std::endl; + top_test = db_test; + } + + // ===================================================================== + // print out a short overview of code used + std::cout <<"//======================================================"<< std::endl; + if ( !printFullInfo ) { + std::cout<<"Printing out light-weight info about branch content and transform matching. " << std::endl; + std::cout<<"Returns the code of first non-trivial difference found: run printFullInfo=True to get the whole list of discrepancies." << std::endl; + } else { + std::cout<<"Printing out detailed info about branch content and transform matching. " << std::endl; + } + std::cout<<"Return value: level*1000 + code OR level*1000 + childNo*10 + code " << std::endl; + std::cout<<" code: 0 no discrepancy found" << std::endl; + std::cout<<" code: 1 name change ( considered trivial ) " << std::endl; + std::cout<<" code: 2 material difference " << std::endl; + std::cout<<" code: 3 shape type change" << std::endl; + std::cout<<" code: 4 shape definition change" << std::endl; + std::cout<<" code: 5 number of child volumes differs" << std::endl; + std::cout<<" code: 6 position (translation) differs" << std::endl; + std::cout<<" code: 7 orientation (rotation) differs" << std::endl; + std::cout<<"Position of alignable objects which show discrepancies is printed out to facilitate interpretation." <<std::endl; + std::cout <<"======================================================//"<< std::endl; + + // ===================================================================== + + std::cout << "Validation strategy A ( assume identity )"<<std::endl; + // prepare arrays to follow matching progress, detect missing objects and duplicates + bool identicalTreeHierarchy = true; + + unsigned int nctest = top_test->getNChildVols(); + unsigned int ncref = top_ref->getNChildVols(); + std::cout << "number of child volumes (ref:test)" << ncref<<":" << nctest<<std::endl; + if (nctest!=ncref) identicalTreeHierarchy = false; + std::string cname,cnameref; + + // test -> ref + int match_code = 0; + for (unsigned int ic = 0; ic < nctest; ic++) { + const GeoVPhysVol* cv = &(*(top_test->getChildVol(ic))); + GeoModelTools::GM_valid mcode( cv, 0, 1, -1,-1); + if (ic>ncref-1) { + m_test2db.push_back(mcode); + continue; + } + GeoTrf::Transform3D tr_test = top_test->getXToChildVol(ic); + GeoTrf::Transform3D tr_ref = top_ref->getXToChildVol(ic); + const GeoVPhysVol* cvref = &(*(top_ref->getChildVol(ic))); + cname = cv->getLogVol()->getName(); + cnameref = cvref->getLogVol()->getName(); + + if (cname!=cnameref) { + m_test2db.push_back(mcode); + identicalTreeHierarchy = false; + continue; + } + + // TODO: match alignables with nearest AND resolve identification + + mcode.valid_position = this->compareTransforms(tr_test,tr_ref, tolerance); + + if (mcode.valid_position==6 && printFullInfo) { + std::cout <<ic<<":"<<cv->getLogVol()->getName()<<" position differs:translation:"<<std::endl; + this->printTranslationDiff( tr_test, tr_ref, tolerance); + } + + if (mcode.valid_position==7 && printFullInfo) { + std::cout <<ic<<":"<<cv->getLogVol()->getName()<<" position differs:rotation:"<<std::endl; + this->printRotationDiff( tr_test, tr_ref, tolerance); + } + + mcode.ref_branch = cvref; + mcode.valid_branch = this->compareGeoVolumes(cv,cvref,tolerance,printFullInfo,0); + + // short printout if no difference found + if (mcode.valid_branch<2 && mcode.valid_position==0) + std::cout << ic<<":"<<cv->getLogVol()->getName()<<":branch content:"<<mcode.valid_branch<<":branch transforms:"<<mcode.valid_position<<std::endl; + else + std::cout << ic<<":"<<cv->getLogVol()->getName()<<":branch content:"<<mcode.valid_branch<<":branch transforms:"<<mcode.valid_position<<" at position:x:y:z:"<<tr_test.translation().x()<<":"<<tr_test.translation().y()<<":"<< tr_test.translation().z()<<std::endl; + + m_test2db.push_back(mcode); + + } + + // run a cross-check: ref->test to spot duplicates; collect non-resolved for more efficient search + std::cout <<" running ref->test check ( search optimization )" << std::endl; + std::vector<const GeoVPhysVol*> ref_nonresolved; + for (unsigned int ic = 0; ic < ncref; ic++) { + const GeoVPhysVol* cvref = &(*(top_ref->getChildVol(ic))); + GeoModelTools::GM_valid mcode( cvref, 0, 1, -1,-1); + if (ic>nctest-1) { + mcode.ref_branch = findBranch(top_test,cvref->getLogVol()->getName(),true,1); + if (mcode.ref_branch) std::cout<<"cross reference found:"<< cvref->getLogVol()->getName() << std::endl; + else ref_nonresolved.push_back(cvref); + m_db2test.push_back(mcode); + continue; + } + const GeoVPhysVol* cv = &(*(top_test->getChildVol(ic))); + cname = cv->getLogVol()->getName(); + cnameref = cvref->getLogVol()->getName(); + + if (cname!=cnameref) { + mcode.ref_branch = findBranch(top_test,cvref->getLogVol()->getName(),true,1); + if (mcode.ref_branch) std::cout<<"cross reference found:"<< cvref->getLogVol()->getName() << std::endl; + else ref_nonresolved.push_back(cvref); + m_db2test.push_back(mcode); + continue; + } + mcode.ref_branch = cv; + mcode.valid_position = m_test2db[ic].valid_position; + mcode.valid_branch = m_test2db[ic].valid_branch; + m_db2test.push_back(mcode); + } + + if ( identicalTreeHierarchy && nctest==ncref ) return; // looks like no further step is needed + + for (auto nonres : ref_nonresolved) std::cout << "non-resolved reference branch:"<< nonres->getLogVol()->getName()<<std::endl; + + //========================================================================== + + std::cout << "Validation strategy B ( resolve alignable stations which were moved in the tree and / or renamed )"<<std::endl; + + for (unsigned int ic = 0; ic < nctest; ic++) { + if (m_test2db[ic].ref_branch) continue; + const GeoVPhysVol* cv = &(*(top_test->getChildVol(ic))); + const GeoVFullPhysVol* cvf = dynamic_cast<const GeoVFullPhysVol*> (cv); + if (!cvf) continue; + cname = cv->getLogVol()->getName(); + GeoTrf::Transform3D tr_test = cvf->getAbsoluteTransform(); + const GeoVPhysVol* cvref = 0; + for (auto nonres : ref_nonresolved) { + cvref = this->findAlignableBranch(nonres,cname,tr_test); // full matching name search + if (!cvref) cvref = this->findAlignableBranch(nonres,cname.substr(m_pnami,m_pnaml),tr_test, false); // partial name matching + if (cvref) break; + } + if (!cvref) cvref = this->findAlignableBranch(top_ref,cname,tr_test); // full matching name search + if (!cvref) cvref = this->findAlignableBranch(top_ref,cname.substr(m_pnami,m_pnaml),tr_test, false); // partial name matching + + m_test2db[ic].valid_strategy = 2; + + if (!cvref) { + std::cout << "unmatched alignable branch :" <<ic <<":"<< cname << std::endl; + continue; + } + + const GeoVFullPhysVol* cvfref = dynamic_cast<const GeoVFullPhysVol*> (cvref); + GeoTrf::Transform3D tr_ref = cvfref->getAbsoluteTransform(); + + m_test2db[ic].valid_position = this->compareTransforms(tr_test,tr_ref, tolerance); + + if (m_test2db[ic].valid_position==6 && printFullInfo ) { + std::cout <<ic<<":"<<cv->getLogVol()->getName()<<" position differs:translation:"<<std::endl; + this->printTranslationDiff( tr_test, tr_ref, tolerance); + } + + if (m_test2db[ic].valid_position==7 && printFullInfo ) { + std::cout <<ic<<":"<<cv->getLogVol()->getName()<<" position differs:rotation:"<<std::endl; + this->printRotationDiff( tr_test, tr_ref, tolerance ); + } + + m_test2db[ic].ref_branch = cvref; + m_test2db[ic].valid_branch = this->compareGeoVolumes(cv,cvref,tolerance,printFullInfo,0); + // short printout if no difference found ( or simple renaming ) + if ( m_test2db[ic].valid_branch<2 && m_test2db[ic].valid_position==0 ) + std::cout << ic<<":"<<cv->getLogVol()->getName()<<":branch content:"<<m_test2db[ic].valid_branch<<":branch transforms:"<<m_test2db[ic].valid_position<<std::endl; + else // print the position as well + std::cout << ic<<":"<<cv->getLogVol()->getName()<<":branch content:"<<m_test2db[ic].valid_branch<<":branch transforms:"<<m_test2db[ic].valid_position<<" at position:x:y:z:"<<tr_test.translation().x()<<":"<<tr_test.translation().y()<<":"<< tr_test.translation().z()<<std::endl; + + } // end loop over tree content + + // TODO add symmetric loop (db2test) to spot missing stations or duplicates + + //========================================================================== + + std::cout << "Validation strategy C ( resolve inert material )"<<std::endl; + + for (unsigned int ic = 0; ic < nctest; ic++) { + if (m_test2db[ic].ref_branch) continue; + const GeoVPhysVol* cv = &(*(top_test->getChildVol(ic))); + const GeoVFullPhysVol* cvf = dynamic_cast<const GeoVFullPhysVol*> (cv); + if (cvf) continue; + cname = cv->getLogVol()->getName(); + m_test2db[ic].valid_strategy = 3; + + const GeoVPhysVol* cvref = this->findBranch(top_ref,cname,true,0); // top level search + if (!cvref) for (auto nonres : ref_nonresolved) { // search in non-resolved ref branches + cvref = this->findBranch(nonres,cname); + if (cvref) break; + } + if (!cvref) cvref = this->findBranch(top_ref,cname); // full search ( time consuming ) + + if (cvref) { + m_test2db[ic].ref_branch = cvref; + m_test2db[ic].valid_branch = this->compareGeoVolumes(cv,cvref,tolerance,printFullInfo,0); + std::cout << ic<<":"<<cv->getLogVol()->getName()<<":branch content:"<<m_test2db[ic].valid_branch<<std::endl; + } else { + // branch does not exist : if logical volume, try to resolve child volumes + m_test2db[ic].valid_strategy = -3; // flip sign to signal abandon of top level object ( TODO: make it recursive for dummy materials ) + for (unsigned int id = 0; id < cv->getNChildVols(); id++) { + const GeoVPhysVol* dv = &(*(cv->getChildVol(id))); + std::string dname = dv->getLogVol()->getName(); + const GeoVPhysVol* dvref = this->findBranch(top_ref,dname); + if (dvref) { + GeoModelTools::GM_valid mcode( dv, dvref, 3, -1,-1); + mcode.valid_branch = this->compareGeoVolumes(dv,dvref,tolerance,printFullInfo,0); + std::cout << ic<<":"<<cname<<":resolved in child branch:"<<id<<":"<<dname<<":content:"<<mcode.valid_branch<<std::endl; + m_test2db.push_back(mcode); // add the resolved child branch to the list for further checks ( material ) + } else { + std::cout << ic<<":"<<cname<<":child branch:"<<dname<<": reference branch not found" << std::endl; + } + } // end loop over child volumes + } // end non-alignable + } // end loop over tree content + + // TODO add symmetric loop (db2test) to spot missing branches or duplicates + +//========================================================================== + + return; // the following is blocked till prototyping scheme is resolved to speed up the processing & check identification + + std::cout << "Validation strategy D ( inclusive mass per branch )"<<std::endl; + + GeoModelTools::GeoMaterialHelper mat_helper; + + for (unsigned int ic = 0; ic < nctest; ic++) { + + if ( m_test2db[ic].ref_branch) + + std::cout <<ic<<m_test2db[ic].test_branch->getLogVol()->getName()<<":inclusive mass of test branch:"<<mat_helper.evaluateMass(m_test2db[ic].test_branch)<<":ref branch:"<< mat_helper.evaluateMass(m_test2db[ic].ref_branch) <<std::endl; + + else std::cout <<ic<<m_test2db[ic].test_branch->getLogVol()->getName()<<":inclusive mass of test branch:"<<mat_helper.evaluateMass(m_test2db[ic].test_branch)<<":ref branch not found:"<<std::endl; + + } + + return; +} + +int GeoModelTools::GeoPhysVolHelper::compareGeoVolumes( const GeoVPhysVol* gv1, const GeoVPhysVol* gv2, float tolerance, bool dumpInfo, int level , int returnCode ) { + + m_diff = returnCode; + + // CASE 1: naming difference + if (gv1->getLogVol()->getName() != gv2->getLogVol()->getName()) { + m_diff = 1000*level+1; + if (dumpInfo) { + std::cout <<"CASE 1: names differ at level:"<<level<<":"<<gv1->getLogVol()->getName() <<":"<<gv2->getLogVol()->getName() << std::endl; + } + // else return m_diff; // the naming change is harmless and can mask more serious problems, continue the loop + } + // CASE 2: material type difference + if (gv1->getLogVol()->getMaterial()->getName() != gv2->getLogVol()->getMaterial()->getName()) { + m_diff = 1000*level+2; + if (dumpInfo) { + std::cout <<"CASE 2: material types differ for volume:"<<gv1->getLogVol()->getName()<<":at level:"<<level<<":"<<gv1->getLogVol()->getMaterial()->getName() <<":differs from:"<<gv2->getLogVol()->getMaterial()->getName() << std::endl; + } + else return m_diff; + } + // CASE 3: shape type difference + if (gv1->getLogVol()->getShape()->type() != gv2->getLogVol()->getShape()->type() ) { + m_diff = 1000*level+3; + if (dumpInfo) { + std::cout <<"CASE 3: shape types differ at level:"<<level<<":volume name:"<<gv1->getLogVol()->getName() <<":shape:"<<gv1->getLogVol()->getShape()->type() <<":shape ref:"<<gv2->getLogVol()->getShape()->type() << std::endl; + } + else return m_diff; + } + // CASE 4: difference in shape definition + if ( !compareShapes( gv1->getLogVol()->getShape(), gv2->getLogVol()->getShape(), tolerance ) ) { + m_diff = 1000*level+4; + if (dumpInfo) { + std::cout <<"CASE 4: shape definition differ at level:"<<level<<":decoding:"<< std::endl; + std::cout <<"(a) decoding shape definition for child volume:"<<gv1->getLogVol()->getName()<< std::endl; + decodeShape(gv1->getLogVol()->getShape()); + std::cout <<"(b) decoding shape definition for child volume:"<<gv2->getLogVol()->getName()<< std::endl; + decodeShape(gv2->getLogVol()->getShape()); + // extract objects for visual inspection + if (m_dump_diff_path!="" ) { + this->saveToDb(gv1, m_dump_diff_path+"/"+gv1->getLogVol()->getName()+"_test.db",true); + this->saveToDb(gv2, m_dump_diff_path+"/"+gv2->getLogVol()->getName()+"_ref.db",true); + } + } + else return m_diff; + } + // CASE 5: difference in the number of child volumes + if (gv1->getNChildVols() != gv2->getNChildVols()) { + m_diff = 1000*level+5; + if (dumpInfo) { + std::cout <<"CASE 5: number of child vols differ at level:"<<level<< ":volume name:"<<gv1->getLogVol()->getName()<<":nChildVols:" <<gv1->getNChildVols()<<":nChildVols ref:"<<gv2->getNChildVols()<< std::endl; + } + else return m_diff; + } + + // CASE 6 & 7: transform to child difference + for (unsigned int ic = 0; ic < gv1->getNChildVols() ; ic++) { + GeoTrf::Transform3D transf1 = gv1->getXToChildVol(ic); + GeoTrf::Transform3D transf2 = gv2->getXToChildVol(ic); + + const GeoVPhysVol* cv1 = &(*(gv1->getChildVol(ic))); + const GeoVPhysVol* cv2 = &(*(gv2->getChildVol(ic))); + + if ((transf1.translation()-transf2.translation()).norm()>tolerance) { + m_diff = 1000*level + 10*ic + 6; + if (dumpInfo) { + std::cout <<"CASE 6: translation differs at level:"<<level<<": between mother and child:"<<gv1->getLogVol()->getName()<<":"<< cv1->getLogVol()->getName()<<std::endl; + this->printTranslationDiff(transf1,transf2,tolerance); + } + else return m_diff; + } + GeoTrf::RotationMatrix3D rot = transf1.rotation()*transf2.rotation().inverse(); + if ( fabs(rot(0,1))>tolerance || fabs(rot(0,2))>tolerance || fabs(rot(1,2))>tolerance) { + m_diff = 1000*level + 10*ic + 7; + if (dumpInfo) { + std::cout <<"CASE 7: rotation differs at level:"<<level<<":between mother and child:"<<gv1->getLogVol()->getName()<<":"<< cv1->getLogVol()->getName()<<std::endl; + this->printRotationDiff(transf1,transf2,tolerance); + } + else return m_diff; + } + + int child_comp = compareGeoVolumes(cv1,cv2,tolerance,dumpInfo,level+1, m_diff); + if (child_comp != m_diff) std::cout <<"WARNING: faulty logic in return code"<<m_diff<<":"<<child_comp << std::endl; + } + + return m_diff; +} + +// temporary, to be replaced by GMIO.h +void GeoModelTools::GeoPhysVolHelper::saveToDb(const GeoVPhysVol* pv, std::string filename, bool silentMode ) { + + std::ifstream infile(filename.c_str()); + + if (infile.good() ) { + if (silentMode ) return; + std::cout << "Warning : file :"<< filename <<" exists already: dump cancelled " << std::endl; + } + + // open the DB connection + GMDBManager db(filename); + + // check the DB connection + if (db.checkIsDBOpen()) { + std::cout << "OK! Database is open!" << std::endl; + } else { + std::cout << "Database ERROR!! Exiting..."<< filename << std::endl; + return; + } + + // Dump the tree volumes to a local file + std::cout << "Dumping the GeoModel geometry to the DB file..." << std::endl; + GeoModelIO::WriteGeoModel dumpGeoModelGraph(db); // init the GeoModel node action + pv->exec(&dumpGeoModelGraph); // visit all GeoModel nodes + dumpGeoModelGraph.saveToDB(); // save to the SQlite DB file + std::cout << "DONE. Geometry saved into "<<filename <<std::endl; + + return; +} + +// temporary, to be replaced by GMIO.h +const GeoVPhysVol* GeoModelTools::GeoPhysVolHelper::retrieveFromDb(std::string filename) const { + + // open the DB + GMDBManager* db = new GMDBManager(filename); + + if (!db->checkIsDBOpen()) { + std::cout << "error in database readout, no GeoVolume retrieved"<< std::endl; + return nullptr; + } + + // setup the GeoModel reader + GeoModelIO::ReadGeoModel readInGeo = GeoModelIO::ReadGeoModel(db); + + // build the GeoModel geometry + const GeoVPhysVol* dbPhys = dynamic_cast<const GeoVPhysVol*>(readInGeo.buildGeoModel()); // builds the GeoModel tree in memory + + return dbPhys; +} + + +const GeoVPhysVol* GeoModelTools::GeoPhysVolHelper::findBranch( const GeoVPhysVol* top, std::string name, bool fullName, int searchDepth ) const { + + const GeoVPhysVol* branch = 0; + if (fullName && name == top->getLogVol()->getName() ) return top; + if (!fullName && top->getLogVol()->getName().find(name)!=std::string::npos ) return top; + GeoModelTools::GeoMaterialHelper mat_helper; + if (!mat_helper.dummy_material(top) && searchDepth>-2) return branch; // stop short of splitting material branch + unsigned int nc = top->getNChildVols(); + std::string cname; + // proceed level by level + for (unsigned int ic = 0; ic < nc; ic++) { + const GeoVPhysVol* cv = &(*(top->getChildVol(ic))); + const GeoLogVol* clv = cv->getLogVol(); + if (fullName && name == clv->getName() ) return cv; + if (!fullName && clv->getName().find(name)!=std::string::npos ) return cv; + } + if (searchDepth==0) return branch; // stop search + int newSearchDepth = ( searchDepth<0 ) ? searchDepth : searchDepth - 1; + for (unsigned int ic = 0; ic < nc; ic++) { + const GeoVPhysVol* cv = &(*(top->getChildVol(ic))); + const GeoLogVol* clv = cv->getLogVol(); + branch = findBranch(cv, name, fullName, newSearchDepth); + if (branch) return branch; + } + return branch; +} + +const GeoVPhysVol* GeoModelTools::GeoPhysVolHelper::findAlignableBranch( const GeoVPhysVol* top, std::string name, GeoTrf::Transform3D transf, bool fullName, int searchDepth ) const { + + const GeoVPhysVol* branch = 0; + GeoModelTools::GeoMaterialHelper mat_helper; + if (!mat_helper.dummy_material(top) && searchDepth>-2) return branch; // stop short of splitting material branch + unsigned int nc = top->getNChildVols(); + std::string cname; double dist; + // compare distance to name-matching objects at the same level + std::pair<const GeoVPhysVol*,double> bestMatch(0,-1.); + for (unsigned int ic = 0; ic < nc; ic++) { + const GeoVPhysVol* cv = &(*(top->getChildVol(ic))); + const GeoLogVol* clv = cv->getLogVol(); + if ((fullName && name == clv->getName()) || (!fullName && clv->getName().find(name)!=std::string::npos) ) { + const GeoVFullPhysVol* cvf = dynamic_cast<const GeoVFullPhysVol*> (cv); + if (cvf) { + GeoTrf::Transform3D trf = cvf->getAbsoluteTransform(); + dist = (trf.translation()-transf.translation()).norm(); + if (bestMatch.second<0. || dist<bestMatch.second ) bestMatch=std::pair<const GeoVPhysVol*,double>(cv,dist); + } + } + } + if ( bestMatch.first) return bestMatch.first; + + // if no match, test next level + if (searchDepth==0) return 0; // stop search + int newSearchDepth = ( searchDepth<0 ) ? searchDepth : searchDepth - 1; + for (unsigned int ic = 0; ic < nc; ic++) { + const GeoVPhysVol* cv = &(*(top->getChildVol(ic))); + branch = findAlignableBranch(cv, name, transf, fullName, newSearchDepth); + if (branch) return branch; + } + + return bestMatch.first; +} + +void GeoModelTools::GeoPhysVolHelper::printInfo(const GeoVPhysVol* pv, int historyDepth) const { + + const GeoLogVol* lv = pv->getLogVol(); + std::cout <<"printInfo : new Object:" << lv->getName() << ", made of " << lv->getMaterial()->getName() << " x0 " + << lv->getMaterial()->getRadLength() << "," << lv->getShape()->type()<<std::endl; + //shapeCnv.decodeShape(lv->getShape()); + int level = 0; + printChildren(pv,level,historyDepth); +} + +void GeoModelTools::GeoPhysVolHelper::printChildren(const GeoVPhysVol* pv, int level, int historyDepth) const { + + // subcomponents + unsigned int nc = pv->getNChildVols(); + level++; std::string cname; if (historyDepth>0 && level > historyDepth) return; + for (unsigned int ic = 0; ic < nc; ic++) { + GeoTrf::Transform3D transf = pv->getXToChildVol(ic); + + const GeoVPhysVol* cv = &(*(pv->getChildVol(ic))); + const GeoFullPhysVol* cfv = dynamic_cast<const GeoFullPhysVol*> (cv); + const GeoLogVol* clv = cv->getLogVol(); + if (ic==0) cname = clv->getName(); + if (cfv) { + //const std::string& fname = new GeoFullPhysVol(*cfv)->getAbsoluteName(); + //std::cout <<"GeoFullPhysVol:"<<clv->getName()<<":identifier:"<<cfv->getId()<< std::endl; + std::cout <<"GeoFullPhysVol:"<<clv->getName()<< std::endl; + } + std::cout <<"subcomponent:" << level<<":"<<ic << ":" << clv->getName() << ", made of " << clv->getMaterial()->getName() + << " x0 " << clv->getMaterial()->getRadLength() << " , " + << clv->getShape()->type() << "," << transf.translation().x() << " " + << transf.translation().y() << " " << transf.translation().z()<<": nChild:"<< cv->getNChildVols() << std::endl;; + + // shapeCnv.decodeShape(clv->getShape()); + + if (ic==0 || clv->getName()!=cname) printChildren(cv,level,historyDepth); + + cname = clv->getName(); + } +} + +bool GeoModelTools::GeoPhysVolHelper::compareShapes( const GeoShape* sh1, const GeoShape* sh2, float tol ) const { + + if (sh1->type() != sh2->type()) return false; + + if ( sh1->type()=="Pgon") { + const GeoPgon* pgon1 = dynamic_cast<const GeoPgon*>(sh1); + const GeoPgon* pgon2 = dynamic_cast<const GeoPgon*>(sh2); + if (!pgon1 || !pgon2) return false; + + if (pgon1->getNPlanes() != pgon2->getNPlanes()) return false; + if (pgon1->getNSides() != pgon2->getNSides()) return false; + if (fabs(pgon1->getSPhi() - pgon2->getSPhi()) > tol) return false; + if (fabs(pgon1->getDPhi() - pgon2->getDPhi()) > tol) return false; + + return true; + + } else if (sh1->type()=="Trd") { + const GeoTrd* trd1 = dynamic_cast<const GeoTrd*> (sh1); + const GeoTrd* trd2 = dynamic_cast<const GeoTrd*> (sh2); + + if ((trd1->getXHalfLength1() - trd2->getXHalfLength1())>tol) return false; + if ((trd1->getXHalfLength2() - trd2->getXHalfLength2())>tol) return false; + if ((trd1->getYHalfLength1() - trd2->getYHalfLength1())>tol) return false; + if ((trd1->getYHalfLength2() - trd2->getYHalfLength2())>tol) return false; + if ((trd1->getZHalfLength() - trd2->getZHalfLength())>tol) return false; + + return true; + + } else if ( sh1->type()=="Box") { + const GeoBox* box1 = dynamic_cast<const GeoBox*> (sh1); + const GeoBox* box2 = dynamic_cast<const GeoBox*> (sh2); + + if (fabs(box1->getXHalfLength() - box2->getXHalfLength()) > tol) return false; + if (fabs(box1->getYHalfLength() - box2->getYHalfLength()) > tol) return false; + if (fabs(box1->getZHalfLength() - box2->getZHalfLength()) > tol) return false; + + return true; + + } else if ( sh1->type() == "Tube" ) { + const GeoTube* tube1=dynamic_cast<const GeoTube*> (sh1); + const GeoTube* tube2=dynamic_cast<const GeoTube*> (sh2); + + if ( fabs(tube1->getRMin() - tube2->getRMin()) > tol) return false; + if ( fabs(tube1->getRMax() - tube2->getRMax()) > tol) return false; + if ( fabs(tube1->getZHalfLength() - tube2->getZHalfLength()) > tol) return false; + + return true; + + } else if ( sh1->type() == "Tubs" ) { + const GeoTubs* tubs1=dynamic_cast<const GeoTubs*> (sh1); + const GeoTubs* tubs2=dynamic_cast<const GeoTubs*> (sh2); + + if ( fabs(tubs1->getRMin() - tubs2->getRMin()) >tol) return false; + if ( fabs(tubs1->getRMax() - tubs2->getRMax()) > tol) return false; + if ( fabs(tubs1->getZHalfLength() - tubs2->getZHalfLength()) > tol) return false; + if ( fabs(tubs1->getSPhi() - tubs2->getSPhi()) > tol) return false; + if ( fabs(tubs1->getDPhi() - tubs2->getDPhi()) > tol) return false; + + return true; + + } else if ( sh1->type() == "Cons" ) { + const GeoCons* cons1=dynamic_cast<const GeoCons*> (sh1); + const GeoCons* cons2=dynamic_cast<const GeoCons*> (sh2); + + if ( fabs(cons1->getRMin1() - cons2->getRMin1()) > tol) return false; + if ( fabs(cons1->getRMin2() - cons2->getRMin2()) >tol) return false; + if ( fabs(cons1->getRMax1() - cons2->getRMax1()) > tol) return false; + if ( fabs(cons1->getRMax2() - cons2->getRMax2()) > tol) return false; + if ( fabs(cons1->getDZ() - cons2->getDZ()) > tol) return false; + if ( fabs(cons1->getSPhi() - cons2->getSPhi()) > tol) return false; + if ( fabs(cons1->getDPhi() - cons2->getDPhi()) > tol) return false; + + return true; + + } else if ( sh1->type()=="SimplePolygonBrep") { + const GeoSimplePolygonBrep* spb1 = dynamic_cast<const GeoSimplePolygonBrep*> (sh1); + const GeoSimplePolygonBrep* spb2 = dynamic_cast<const GeoSimplePolygonBrep*> (sh2); + if (!spb1 || !spb2) return false; + + unsigned int nv1 = spb1->getNVertices(); + unsigned int nv2 = spb2->getNVertices(); + if (nv1 != nv2) return false; + if (fabs(spb1->getDZ() - spb2->getDZ()) > tol) return false; + + for (unsigned int iv = 0; iv < nv1; iv++) { + + if (fabs(spb1->getXVertex(iv) - spb2->getXVertex(iv)) > tol) return false; + if (fabs(spb1->getYVertex(iv) - spb2->getYVertex(iv)) > tol) return false; + } + + return true; + + } else if ( sh1->type()=="Pcon") { + const GeoPcon* pc1 = dynamic_cast<const GeoPcon*> (sh1); + const GeoPcon* pc2 = dynamic_cast<const GeoPcon*> (sh2); + if (!pc1 || !pc2) return false; + + if ( fabs(pc1->getSPhi() - pc2->getSPhi()) > tol) return false; + if ( fabs(pc1->getDPhi() - pc2->getDPhi()) > tol) return false; + + unsigned int nv1 = pc1->getNPlanes(); + unsigned int nv2 = pc2->getNPlanes(); + if (nv1 != nv2) return false; + + for (unsigned int iv = 0; iv < nv1; iv++) { + + if (fabs(pc1->getZPlane(iv) - pc2->getZPlane(iv)) > tol) return false; + if (fabs(pc1->getRMinPlane(iv) - pc2->getRMinPlane(iv)) > tol) return false; + if (fabs(pc1->getRMaxPlane(iv) - pc2->getRMaxPlane(iv)) > tol) return false; + } + + return true; + + } else if ( sh1->type()=="Subtraction") { + const GeoShapeSubtraction* sub1 = dynamic_cast<const GeoShapeSubtraction*> (sh1); + const GeoShapeSubtraction* sub2 = dynamic_cast<const GeoShapeSubtraction*> (sh2); + + if (!sub1 || !sub2) return false; + + if (!compareShapes(sub1->getOpA(),sub2->getOpA(),tol)) return false; + if (!compareShapes(sub1->getOpB(),sub2->getOpB(),tol)) return false; + + return true; + + } else if ( sh1->type()=="Union") { + const GeoShapeUnion* sub1 = dynamic_cast<const GeoShapeUnion*> (sh1); + const GeoShapeUnion* sub2 = dynamic_cast<const GeoShapeUnion*> (sh2); + + if (!sub1 || !sub2) return false; + + if (!compareShapes(sub1->getOpA(),sub2->getOpA(),tol)) return false; + if (!compareShapes(sub1->getOpB(),sub2->getOpB(),tol)) return false; + + return true; + + } else if ( sh1->type()=="Shift") { + const GeoShapeShift* shift1 = dynamic_cast<const GeoShapeShift*> (sh1); + const GeoShapeShift* shift2 = dynamic_cast<const GeoShapeShift*> (sh2); + + if (!shift1 || !shift2) return false; + + if (!compareShapes(shift1->getOp(),shift2->getOp(),tol)) return false; + + const GeoTrf::Transform3D& transf1 = shift1->getX(); + const GeoTrf::Transform3D& transf2 = shift2->getX(); + + if ((transf1.translation()-transf2.translation()).norm()>tol) return false; + + if (!identity_check(transf1.rotation()*transf2.rotation().inverse(), tol)) return false; + + return true; + } + + std::cout <<"unknown shape to compare:"<<sh1->type()<< std::endl; + + return false; + +} + +bool GeoModelTools::GeoPhysVolHelper::identity_check(GeoTrf::RotationMatrix3D rotation, float tol) const { + + if (fabs(rotation(0,1))>tol) return false; + if (fabs(rotation(0,2))>tol) return false; + if (fabs(rotation(1,2))>tol) return false; + + return true; +} + +void GeoModelTools::GeoPhysVolHelper::decodeShape(const GeoShape* sh) const { + + std::cout << "decoding shape:"<< sh->type() << std::endl; + + if ( sh->type()=="Trd") { + const GeoTrd* trd = dynamic_cast<const GeoTrd*> (sh); + std::cout << "dimensions:" << trd->getXHalfLength1() << "," + << trd->getXHalfLength2() << "," + << trd->getYHalfLength1() << "," + << trd->getYHalfLength2() << "," + << trd->getZHalfLength() << std::endl; + } + + if ( sh->type()=="SimplePolygonBrep") { + const GeoSimplePolygonBrep* spb = dynamic_cast<const GeoSimplePolygonBrep*> (sh); + + int nv = spb->getNVertices(); + std::cout <<"number of planes: dZ:"<<nv<<":"<<spb->getDZ()<< std::endl; + + for (unsigned int iv = 0; iv < nv; iv++) { + + std::cout <<"x,y:"<<spb->getXVertex(iv)<<","<<spb->getYVertex(iv)<< std::endl; + } + } + + + if ( sh->type()=="Subtraction") { + const GeoShapeSubtraction* sub = dynamic_cast<const GeoShapeSubtraction*> (sh); + const GeoShape* sha = sub->getOpA(); + const GeoShape* shs = sub->getOpB(); + std::cout << "decoding subtracted shape:" << std::endl; + decodeShape(sha); + decodeShape(shs); + } + + if ( sh->type()=="Union") { + const GeoShapeUnion* sub = dynamic_cast<const GeoShapeUnion*> (sh); + const GeoShape* shA = sub->getOpA(); + const GeoShape* shB = sub->getOpB(); + std::cout << "decoding shape A:" << std::endl; + decodeShape(shA); + std::cout << "decoding shape B:" << std::endl; + decodeShape(shB); + } + + if ( sh->type()=="Shift") { + const GeoShapeShift* shift = dynamic_cast<const GeoShapeShift*> (sh); + const GeoShape* shA = shift->getOp(); + const GeoTrf::Transform3D& transf = shift->getX(); + std::cout << "shifted by:x:y:z:" <<transf.translation().x()<<":"<<transf.translation().y()<<":"<<transf.translation().z()<<std::endl; + std::cout <<"rotation diag:"<< transf(0,0)<<"," << transf(1,1) <<"," << transf(2,2) << std::endl; + decodeShape(shA); + } + +} + +int GeoModelTools::GeoPhysVolHelper::compareTransforms(GeoTrf::Transform3D tr_test, GeoTrf::Transform3D tr_ref, float tolerance) const { + + int trcode = 0; // assuming identical + + if ((tr_test.translation()-tr_ref.translation()).norm()>tolerance) trcode = 6; + + if (!identity_check(tr_test.rotation()*tr_ref.rotation().inverse(), tolerance)) trcode = 7; + + return trcode; +} + +void GeoModelTools::GeoPhysVolHelper::printTranslationDiff(GeoTrf::Transform3D tr_test, GeoTrf::Transform3D tr_ref, float tolerance) const { + + std::cout << std::fixed << std::setprecision(4); + std::cout << "test translation:x:y:z:" << tr_test.translation().x() <<":" << tr_test.translation().y() <<":" << tr_test.translation().z() <<std::endl; + std::cout << " ref translation:x:y:z:" << tr_ref.translation().x() <<":" << tr_ref.translation().y() <<":" << tr_ref.translation().z() <<std::endl; + std::cout <<" absolute shift :" << (tr_test.translation()-tr_ref.translation()).norm()<<": to be compared with the tolerance limit:"<<tolerance<< std::endl; + +} + +void GeoModelTools::GeoPhysVolHelper::printRotationDiff(GeoTrf::Transform3D tr_test, GeoTrf::Transform3D tr_ref, float tolerance) const { + + GeoTrf::RotationMatrix3D rotest = tr_test.rotation(); + GeoTrf::RotationMatrix3D rotref = tr_ref.rotation(); + GeoTrf::RotationMatrix3D rotid = rotest*rotref.inverse(); + + std::cout << std::fixed << std::setprecision(4); + std::cout << "test rotation:" << rotest(0,0) <<":" << rotest(0,1) <<":" << rotest(0,2) <<std::endl; + std::cout << " " << rotest(1,0) <<":" << rotest(1,1) <<":" << rotest(1,2) <<std::endl; + std::cout << " " << rotest(2,0) <<":" << rotest(2,1) <<":" << rotest(2,2) <<std::endl; + std::cout << " ref rotation:" << rotref(0,0) <<":" << rotref(0,1) <<":" << rotref(0,2) <<std::endl; + std::cout << " " << rotref(1,0) <<":" << rotref(1,1) <<":" << rotref(1,2) <<std::endl; + std::cout << " " << rotref(2,0) <<":" << rotref(2,1) <<":" << rotref(2,2) <<std::endl; + std::cout << "test*inv(ref):" << rotid(0,0) <<":" << rotid(0,1) <<":" << rotid(0,2) <<std::endl; + std::cout << " " << rotid(1,0) <<":" << rotid(1,1) <<":" << rotid(1,2) <<std::endl; + std::cout << " " << rotid(2,0) <<":" << rotid(2,1) <<":" << rotid(2,2) <<std::endl; + std::cout <<" identity check fails within the tolerance limit:"<<tolerance<< std::endl; + +} diff --git a/GeoModelTools/GeoModelXML/GMXPlugin/src/GMXPlugin.cxx b/GeoModelTools/GeoModelXML/GMXPlugin/src/GMXPlugin.cxx index 08292ec0b04daf531816833759c94d8bcde1c17a..9aea247992b7f0cd26815e0634e0b31d8324e316 100644 --- a/GeoModelTools/GeoModelXML/GMXPlugin/src/GMXPlugin.cxx +++ b/GeoModelTools/GeoModelXML/GMXPlugin/src/GMXPlugin.cxx @@ -1,11 +1,12 @@ /* - Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ #include "GeoModelKernel/GeoVGeometryPlugin.h" +#include "GeoModelKernel/GeoPhysVol.h" #include "GeoModelKernel/GeoNameTag.h" #include "GeoModelKernel/Units.h" #define SYSTEM_OF_UNITS GeoModelKernelUnits // so we will get, e.g., 'GeoModelKernelUnits::cm' @@ -31,7 +32,7 @@ class GMXPlugin : public GeoVGeometryPlugin { ~GMXPlugin(); // Creation of geometry: - virtual void create(GeoPhysVol *world, bool publish) override; + virtual void create(GeoVPhysVol *world, bool publish) override; private: @@ -78,7 +79,7 @@ GMXPlugin::~GMXPlugin() //## Other Operations (implementation) -void GMXPlugin::create(GeoPhysVol *world, bool publish) +void GMXPlugin::create(GeoVPhysVol *world, bool publish) { std::cout<< "This is GMXPlugin: creating a GeoModelXml detector "<<std::endl; std::vector<std::string> filesToParse; diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/CMakeLists.txt b/GeoModelTools/GeoModelXML/GeoModelXml/CMakeLists.txt index 29a9b69bcf7bfcc514125ad3feb088b01f2ea2b7..67c34087f1161b1006d1895b35ec8f5449390562 100644 --- a/GeoModelTools/GeoModelXML/GeoModelXml/CMakeLists.txt +++ b/GeoModelTools/GeoModelXML/GeoModelXml/CMakeLists.txt @@ -13,7 +13,7 @@ find_package( ZLIB REQUIRED ) # Create the library. add_library( GeoModelXml SHARED ${HEADERS} ${SOURCES} ) # link libraries -target_link_libraries( GeoModelXml PUBLIC GeoModelCore::GeoModelKernel GeoModelTools::ExpressionEvaluator XercesC::XercesC PRIVATE ZLIB::ZLIB ) +target_link_libraries( GeoModelXml PUBLIC GeoModelCore::GeoModelKernel GeoModelCore::GeoModelFuncSnippets GeoModelTools::ExpressionEvaluator XercesC::XercesC PRIVATE ZLIB::ZLIB ) target_include_directories( GeoModelXml PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> $<INSTALL_INTERFACE:include> ) diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/Gmx2Geo.h b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/Gmx2Geo.h index c2777264df453490229768ec3e87b0b3d88f4ef6..30a90db1f26d11f978886729a864272addea3097 100644 --- a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/Gmx2Geo.h +++ b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/Gmx2Geo.h @@ -58,7 +58,7 @@ class IEvaluator; class Gmx2Geo { public: - Gmx2Geo(const std::string& gmxFile, GeoPhysVol *addHere, GmxInterface &gmxInterface, unsigned int flags = 0, bool useMatManager = 0, std::string levelMapName = "", const processorList& procs=processorList()); + Gmx2Geo(const std::string& gmxFile, GeoVPhysVol *addHere, GmxInterface &gmxInterface, unsigned int flags = 0, bool useMatManager = 0, std::string levelMapName = "", const processorList& procs=processorList()); private: // Disallow copying Gmx2Geo(const Gmx2Geo &right); diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/src/Gmx2Geo.cxx b/GeoModelTools/GeoModelXML/GeoModelXml/src/Gmx2Geo.cxx index 8274bd071b1f955c622bb81c9c8758aa17a4a5e4..5de2274ad1f524e817b0d1519d0ded6775421ea1 100644 --- a/GeoModelTools/GeoModelXML/GeoModelXml/src/Gmx2Geo.cxx +++ b/GeoModelTools/GeoModelXML/GeoModelXml/src/Gmx2Geo.cxx @@ -33,7 +33,7 @@ using namespace std; using namespace xercesc; -Gmx2Geo::Gmx2Geo(const string& xmlFile, GeoPhysVol *addHere, GmxInterface &gmxInterface, unsigned int flags, bool useMatManager, std::string levelMapName, const processorList& procs) { +Gmx2Geo::Gmx2Geo(const string& xmlFile, GeoVPhysVol *addHere, GmxInterface &gmxInterface, unsigned int flags, bool useMatManager, std::string levelMapName, const processorList& procs) { // // Create the xml tree (DOMDocument) // @@ -426,4 +426,4 @@ for (auto param:params){ } data.push_back(param.second); } -} \ No newline at end of file +} diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/src/GmxInterface.cxx b/GeoModelTools/GeoModelXML/GeoModelXml/src/GmxInterface.cxx index 47b6edf0b7159648ce06d26a07fe848d21cb73ed..2458dd49bfaca0513ee6935366b790a54bbcaf0c 100644 --- a/GeoModelTools/GeoModelXML/GeoModelXml/src/GmxInterface.cxx +++ b/GeoModelTools/GeoModelXML/GeoModelXml/src/GmxInterface.cxx @@ -13,7 +13,6 @@ // #include "GeoModelXml/GmxInterface.h" #include "OutputDirector.h" -#include "GeoModelKernel/GeoPVConstLink.h" #include "GeoModelKernel/Query.h" #include "GeoModelKernel/GeoPhysVol.h" #include "GeoModelKernel/GeoVFullPhysVol.h" @@ -22,12 +21,12 @@ using namespace std; int GmxInterface::sensorId(map<string, int> &/*index*/) const { - static std::atomic<int> sequentialId; + static std::atomic<int> sequentialId{0}; return sequentialId++; } int GmxInterface::splitSensorId(map<string, int> &/*index*/, std::pair<std::string, int> &/*extraIndex*/, map<string, int> &/*updatedIndex*/) const { - static std::atomic<int> sequentialId; + static std::atomic<int> sequentialId{0}; return sequentialId++; } diff --git a/GeoModelTools/GeoModelXML/README.md b/GeoModelTools/GeoModelXML/README.md index bdbac4ff6bf412660f04e20eb8d5a31b9a0b9651..e02bef58ecac29699b69f4f5a094755276e7412d 100644 --- a/GeoModelTools/GeoModelXML/README.md +++ b/GeoModelTools/GeoModelXML/README.md @@ -3,7 +3,7 @@ This package contains a modernised version of Nigel Hessey's GeoModelXml to be used with `gmex` (GeoModelExplorer) and the corresponding plugin (GMXPlugin) -Installation requires that the [GeoModel](https://gitlab.cern.ch/GeoModelDev/GeoModel) suite is installed. Please refer to https://gitlab.cern.ch/GeoModelDev/GeoModel/-/blob/master/README.md for additional documentation. +Installation requires that the [GeoModel](https://gitlab.cern.ch/GeoModelDev/GeoModel) suite is installed. Please refer to https://gitlab.cern.ch/GeoModelDev/GeoModel/-/blob/main/README.md for additional documentation. ## Nigel's documentation diff --git a/GeoModelTools/GeoModelXMLParser/CMakeLists.txt b/GeoModelTools/GeoModelXMLParser/CMakeLists.txt index e61982075c20300de6f7e400fa14b21fc89cf45f..4ec001e6c47b49d9bdbfda6bfc1f61f02ebdb365 100644 --- a/GeoModelTools/GeoModelXMLParser/CMakeLists.txt +++ b/GeoModelTools/GeoModelXMLParser/CMakeLists.txt @@ -6,10 +6,6 @@ file( GLOB HEADERS GeoModelXMLParser/*.h ) # Create the library. add_library( GeoModelXMLParser SHARED ${HEADERS} ${SOURCES} ) -# If the in-house build of the Xerces-C library is used, add explicit dependency -if( GEOMODEL_USE_BUILTIN_XERCESC ) - add_dependencies( GeoModelXMLParser XercesCBuiltIn ) -endif() target_link_libraries( GeoModelXMLParser PUBLIC XercesC::XercesC ExpressionEvaluator ) target_include_directories( GeoModelXMLParser PUBLIC diff --git a/GeoModelVisualization/CMakeLists.txt b/GeoModelVisualization/CMakeLists.txt index 054444a47a272f347c06333958252d30bdc31b3d..bd48e96958c9c4e4cf1bba3f72538118a08fc38e 100644 --- a/GeoModelVisualization/CMakeLists.txt +++ b/GeoModelVisualization/CMakeLists.txt @@ -1,7 +1,7 @@ # Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration # CMake settings -cmake_minimum_required( VERSION 3.14 ) +cmake_minimum_required(VERSION 3.16...3.26) # Dummy call to 'project()', needed to set 'PROJECT_SOURCE_DIR' project( "GeoModelTools" ) @@ -9,6 +9,7 @@ project( "GeoModelTools" ) #Set up the project. Check if we build it with GeoModel or individually project( "GeoModelVisualization" ) + # Set the OpenGL flag requested by CMake set( OpenGL_GL_PREFERENCE GLVND ) @@ -20,6 +21,17 @@ if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) include( GeoModel-version ) # set the project, with the version taken from the GeoModel parent project project( "GeoModelVisualization" VERSION ${GeoModel_VERSION} LANGUAGES CXX ) + + #Choose QT version here: + option (GEOMODEL_USE_QT6 "Use Qt6 for Visualization" OFF) + + if (GEOMODEL_USE_QT6) + set (QT_VERSION 6) + else() + set (QT_VERSION 5) + endif() + + # Define color codes for CMake messages include( cmake_colors_defs ) # Warn the users about what they are doing @@ -33,8 +45,6 @@ if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) # Find the base GeoModel packages, which must be installed on the target system already find_package( GeoModelCore REQUIRED ${GeoModel_VERSION} ) find_package( GeoModelIO REQUIRED ${GeoModel_VERSION} ) - # Set a flag to steer the build of the subpackages - set( VISUALIZATION_INDIVIDUAL_BUILD ON ) # Print Build Info on screen include( PrintBuildInfo ) else() @@ -45,7 +55,11 @@ else() endif() # Find the dependencies of the project. -find_package( Qt5 COMPONENTS Core Gui Widgets Sql PrintSupport OpenGL REQUIRED ) +if (GEOMODEL_USE_QT6) + find_package( Qt${QT_VERSION} COMPONENTS Core Gui Widgets Sql PrintSupport OpenGL Core5Compat REQUIRED ) +else () + find_package( Qt${QT_VERSION} COMPONENTS Core Gui Widgets Sql PrintSupport OpenGL REQUIRED ) +endif() find_package( OpenGL REQUIRED ) find_package( HDF5 REQUIRED COMPONENTS CXX ) # Set up how the project should handle some of its dependenices. Either by @@ -53,7 +67,7 @@ find_package( HDF5 REQUIRED COMPONENTS CXX ) include( SetupCoin3D ) include( SetupJSON ) -# Qt5 settings. +# Qt${QT_VERSION} settings. set( CMAKE_AUTOMOC ON ) set( CMAKE_AUTOUIC ON ) set( CMAKE_AUTORCC ON ) diff --git a/GeoModelVisualization/GXClashPointSystems/CMakeLists.txt b/GeoModelVisualization/GXClashPointSystems/CMakeLists.txt index 6984a09c9c5eea3dd845cbf35e2d53f0c52ccd13..33c91f302076873b65ae865c164fe8ce28036cf8 100644 --- a/GeoModelVisualization/GXClashPointSystems/CMakeLists.txt +++ b/GeoModelVisualization/GXClashPointSystems/CMakeLists.txt @@ -9,7 +9,7 @@ file( GLOB UIS src/*.ui ) add_library( GXClashPointSystems SHARED ${SOURCES} ${HEADERS} ${UIS} ) target_link_libraries( GXClashPointSystems PUBLIC Coin::Coin GXBase - PRIVATE Qt5::Core Qt5::Widgets nlohmann_json::nlohmann_json ) + PRIVATE Qt${QT_VERSION}::Core Qt${QT_VERSION}::Widgets nlohmann_json::nlohmann_json ) target_include_directories( GXClashPointSystems PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> $<INSTALL_INTERFACE:include> ) @@ -21,9 +21,6 @@ set_target_properties( GXClashPointSystems PROPERTIES if( GEOMODEL_USE_BUILTIN_COIN3D ) add_dependencies( GXClashPointSystems Coin3DBuiltIn ) endif() -if( GEOMODEL_USE_BUILTIN_JSON ) - add_dependencies( GXClashPointSystems JSONExt ) -endif() # Set up an alias with the same name that you would get by "finding" a pre-built # version of the library. diff --git a/GeoModelVisualization/GXHitDisplaySystems/CMakeLists.txt b/GeoModelVisualization/GXHitDisplaySystems/CMakeLists.txt index 6637e020d8f1144db3c3632cbf85051d6c462fb9..e1e2c7d83af1ec32068af5a2fb2726219f93bd0f 100644 --- a/GeoModelVisualization/GXHitDisplaySystems/CMakeLists.txt +++ b/GeoModelVisualization/GXHitDisplaySystems/CMakeLists.txt @@ -9,7 +9,7 @@ find_package (HDF5 REQUIRED) add_library( GXHitDisplaySystems SHARED ${SOURCES} ${HEADERS} ${UIS} ) target_link_libraries( GXHitDisplaySystems PUBLIC Coin::Coin GXBase - PRIVATE Qt5::Core Qt5::Widgets ${HDF5_CXX_LIBRARIES} ${HDF5_LIBRARIES} ) + PRIVATE Qt${QT_VERSION}::Core Qt${QT_VERSION}::Widgets ${HDF5_CXX_LIBRARIES} ${HDF5_LIBRARIES} ) target_include_directories( GXHitDisplaySystems PUBLIC ${HDF5_CXX_INCLUDE_DIRS} $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> diff --git a/GeoModelVisualization/GXTrackDisplaySystems/CMakeLists.txt b/GeoModelVisualization/GXTrackDisplaySystems/CMakeLists.txt index 475be0827a58bae7633a2681c79b5c20aba6b463..bc690cd322d977679d27a1ff98a6734f35dc6c00 100644 --- a/GeoModelVisualization/GXTrackDisplaySystems/CMakeLists.txt +++ b/GeoModelVisualization/GXTrackDisplaySystems/CMakeLists.txt @@ -9,7 +9,7 @@ file( GLOB UIS src/*.ui ) add_library( GXTrackDisplaySystems SHARED ${SOURCES} ${HEADERS} ${UIS} ) target_link_libraries( GXTrackDisplaySystems PUBLIC Coin::Coin GXBase - PRIVATE Qt5::Core Qt5::Widgets ${HDF5_LIBRARIES} ) + PRIVATE Qt${QT_VERSION}::Core Qt${QT_VERSION}::Widgets ${HDF5_LIBRARIES} ) target_include_directories( GXTrackDisplaySystems PUBLIC ${HDF5_CXX_INCLUDE_DIRS} $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> diff --git a/GeoModelVisualization/GeoModelExplorer/CMakeLists.txt b/GeoModelVisualization/GeoModelExplorer/CMakeLists.txt index b41741b94c974c1a56ac2c1b06536f1636494bb0..695376de66e41b81e109f7e6d6b10e884b1497c2 100644 --- a/GeoModelVisualization/GeoModelExplorer/CMakeLists.txt +++ b/GeoModelVisualization/GeoModelExplorer/CMakeLists.txt @@ -5,7 +5,7 @@ add_executable( gmex src/main.cxx ) add_definitions (-DGXPLUGINDIR="${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/gxplugins" ) -target_link_libraries( gmex PRIVATE GXGui Qt5::Core ) +target_link_libraries( gmex PRIVATE GXGui Qt${QT_VERSION}::Core ) target_compile_definitions( gmex PRIVATE GEOMODEL_INSTALL_PREFIX="${CMAKE_INSTALL_PREFIX}" ) source_group( "src" FILES "src/main.cxx" ) diff --git a/GeoModelVisualization/VP1Base/CMakeLists.txt b/GeoModelVisualization/VP1Base/CMakeLists.txt index 4297266813d9d1220a75c553dfa1aaccfaec0a7a..ca2b6aba0e2e94d3986fa6d37a0d12773f78334c 100644 --- a/GeoModelVisualization/VP1Base/CMakeLists.txt +++ b/GeoModelVisualization/VP1Base/CMakeLists.txt @@ -8,9 +8,16 @@ file( GLOB RCS src/*.qrc ) # Add the library. add_library( GXBase SHARED ${SOURCES} ${HEADERS} ${UIS} ${RCS} ) -target_link_libraries( GXBase - PUBLIC Coin::Coin Qt5::Core Qt5::Gui Qt5::Widgets SoQt::SoQt - PRIVATE Qt5::PrintSupport Qt5::OpenGL GXHEPVis ) +if (GEOMODEL_USE_QT6) + target_link_libraries( GXBase + PUBLIC Coin::Coin Qt${QT_VERSION}::Core Qt${QT_VERSION}::Gui Qt${QT_VERSION}::Widgets Qt${QT_VERSION}::Core5Compat SoQt::SoQt + PRIVATE Qt${QT_VERSION}::PrintSupport Qt${QT_VERSION}::OpenGL GXHEPVis ) +else() + target_link_libraries( GXBase + PUBLIC Coin::Coin Qt${QT_VERSION}::Core Qt${QT_VERSION}::Gui Qt${QT_VERSION}::Widgets SoQt::SoQt + PRIVATE Qt${QT_VERSION}::PrintSupport Qt${QT_VERSION}::OpenGL GXHEPVis ) +endif() + target_include_directories( GXBase PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> $<INSTALL_INTERFACE:include> ) diff --git a/GeoModelVisualization/VP1Base/VP1Base/AnimationSequencer.h b/GeoModelVisualization/VP1Base/VP1Base/AnimationSequencer.h index 6931c748486ad8a6b6046336ac467b9ad191393a..d29dc8ff35f4f96341548161a93ca2ce11bb855e 100644 --- a/GeoModelVisualization/VP1Base/VP1Base/AnimationSequencer.h +++ b/GeoModelVisualization/VP1Base/VP1Base/AnimationSequencer.h @@ -13,7 +13,7 @@ #include "VP1Base/AnimationSequence.h" #include <QObject> - +#include <QGraphicsItem> class VP1ExaminerViewer; class AnimationSequencer : public QObject { diff --git a/GeoModelVisualization/VP1Base/VP1Base/IVP12DDetViewsChannelWidget.h b/GeoModelVisualization/VP1Base/VP1Base/IVP12DDetViewsChannelWidget.h deleted file mode 100644 index a377e984118faffadcf007bf48b6bfda84903191..0000000000000000000000000000000000000000 --- a/GeoModelVisualization/VP1Base/VP1Base/IVP12DDetViewsChannelWidget.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -*/ - -///////////////////////////////////////////////////////////// -// // -// Header file for class IVP12DDetViewsChannelWidget // -// // -// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // -// // -// Initial version: July 2007 // -// // -///////////////////////////////////////////////////////////// - -#ifndef IVP12DDETVIEWSCHANNELWIDGET_H -#define IVP12DDETVIEWSCHANNELWIDGET_H - -#include "VP1Base/IVP1ChannelWidget.h" - - -//This type of channel widget displays itemcollections in two -//different graphicsviews - one for each of XY and RZ -//projections. -// -//The normal way to add data from systems into these views is to add a -//number of IVP12DDetViewsSystem's to the channel (using the addSystem -//method) methods. Since IVP12DDetViewsSystem's specifically provide -//item collections for each of the different projections, everything -//should be taken care of automatically. It is, however, possible to -//add collections from any IVP12DSystem to the views. To do this, one -//must use the addGeneralSystem method and specify as a parameter in -//which of the two projections all of the item collections provided -//by this system should be presented. - -//fixme/TODO: Actually use the z-factor!! - -class IVP12DSystem; -class IVP12DDetViewsSystem; - -class IVP12DDetViewsChannelWidget : public IVP1ChannelWidget { - - Q_OBJECT - -public: - IVP12DDetViewsChannelWidget(const QString & name, const QString & information, const QString & contact_info); - //Fixme: Pass along default backgroundcolor as an option? - -protected: - enum SystemOption { - AllowAll = 0x0000, - DisallowSelections = 0x0100,//User can not interact with items from this system (movable though, is handled separately) - DisallowSwitchable = 0x0400,//User can not turn items from this system on/off. - DisallowController = 0x0800,//Custom controllers provided by this wont be present in the GUI - DisallowMovable = 0x1000,//Items from this systems are never movable - StartDisabled = 0x0010 - }; -public: //public instead of protected due to compilation problems on SLC3 - Q_DECLARE_FLAGS(SystemOptions, SystemOption) -protected: - //Call the following in constructor of a derived class to add 2D systems. Never delete the systems in the derived class. - - //Zfactor determines which systems are on top of each other (higher values are in the foreground) //FIXME - NOT USED!!! - - void addSystem(IVP12DDetViewsSystem*, double zfactor, const SystemOptions& options = AllowAll ); - - //Other types of systems can only be used by adding all of their collections into a single given projection view: - enum PROJECTION { XY, RZ }; - void addGeneralSystem(IVP12DSystem*, const PROJECTION& projection, double zfactor, const SystemOptions& options = AllowAll );//FIXME: NOT IMPLEMENTED YET!!!!!! - - //////////////////// The following is for internal use /////////////////////// - -public: - Type type() const { return TWODIMENSIONAL; }; - - void create(); - void systemRefreshed(IVP1System*); - void systemErased(IVP1System*); - virtual ~IVP12DDetViewsChannelWidget(); - virtual QByteArray saveState(); - virtual void restoreFromState(QByteArray); - -protected slots: - void showControlsForSystem(); - -private: - class Imp; - Imp * m_d; -private slots: - void toggleSystemActive(); - void setBackgroundColor(const QColor &); -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS(IVP12DDetViewsChannelWidget::SystemOptions) - -#endif diff --git a/GeoModelVisualization/VP1Base/VP1Base/IVP12DDetViewsSystem.h b/GeoModelVisualization/VP1Base/VP1Base/IVP12DDetViewsSystem.h deleted file mode 100644 index 764746986cfa0fc7f17972547c5b5ee9821fe3e4..0000000000000000000000000000000000000000 --- a/GeoModelVisualization/VP1Base/VP1Base/IVP12DDetViewsSystem.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -*/ - -///////////////////////////////////////////////////////////// -// // -// Header file for class IVP12DDetViewsSystem // -// // -// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // -// // -// Initial version: July 2007 // -// // -///////////////////////////////////////////////////////////// - -#ifndef IVP12DDETVIEWSSYSTEM_H -#define IVP12DDETVIEWSSYSTEM_H - -#include "VP1Base/IVP12DSystem.h" - -#include <QSet> - -class VP1GraphicsItemCollection; - -class IVP12DDetViewsSystem : public IVP12DSystem { - - Q_OBJECT - -public: - - //////////////////////////////////////////////////////////////////////// - ////////////// This is the interesting bit for those ////////////// - ////////////// who are deriving from this class... ////////////// - //////////////////////////////////////////////////////////////////////// - - IVP12DDetViewsSystem(const QString & name, const QString & information, const QString & contact_info); - - virtual void systemcreate(StoreGateSvc* detstore);//Optional. - - //If you need a controller - create it and return it from a reimplementation of this method (it will only be called once). - virtual QWidget * buildController(); - - //If some items should be visible for the entire run, reimplement: - virtual void buildPermanentItemCollections( StoreGateSvc* detstore, - VP1GraphicsItemCollection* ic_xy, - VP1GraphicsItemCollection* ic_rz ); - - //Reimplement and add the items for a given event, based on the contents of storegate: - virtual void buildEventItemCollections( StoreGateSvc *sg, - VP1GraphicsItemCollection* ic_xy, - VP1GraphicsItemCollection* ic_rz ); - - virtual void systemerase();//Optional - for erasing maps etc. with event data. - - virtual void systemuncreate();//Optional. - - - //This is the interesting bit for channels using this system: - QSet<VP1GraphicsItemCollection*> getItemCollections_XY() const; - QSet<VP1GraphicsItemCollection*> getItemCollections_RZ() const; - - //////////////////////////////////////////////////////////////////////// - //////////// The rest of this file is just internal stuff //////////// - //////////// - dont worry about it - //////////// - //////////////////////////////////////////////////////////////////////// - - virtual ~IVP12DDetViewsSystem(); -private: - class Imp; - Imp * m_d; - void create(StoreGateSvc* detstore); - void refresh(StoreGateSvc* storegate); - void erase(); - void uncreate(); -}; - - - -#endif diff --git a/GeoModelVisualization/VP1Base/VP1Base/IVP12DStandardChannelWidget.h b/GeoModelVisualization/VP1Base/VP1Base/IVP12DStandardChannelWidget.h deleted file mode 100644 index 190b0fa6441bc8c59bbf4d43a6e0b7ea5fab36aa..0000000000000000000000000000000000000000 --- a/GeoModelVisualization/VP1Base/VP1Base/IVP12DStandardChannelWidget.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -*/ - -///////////////////////////////////////////////////////////// -// // -// Header file for class IVP12DStandardChannelWidget // -// // -// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // -// // -// Initial version: April 2007 // -// // -///////////////////////////////////////////////////////////// - -#ifndef IVP12DSTANDARDCHANNELWIDGET_H -#define IVP12DSTANDARDCHANNELWIDGET_H - -#include "VP1Base/IVP1ChannelWidget.h" -class IVP12DSystem; -class IVP12DSystemSimple; - -class IVP12DStandardChannelWidget : public IVP1ChannelWidget { - - Q_OBJECT - -public: - IVP12DStandardChannelWidget(const QString & name, const QString & information, const QString & contact_info); - //Fixme: Pass along default backgroundcolor as an option? - -protected: - enum SystemOption { - AllowAll = 0x0000, - DisallowSelections = 0x0100,//User can not interact with items from this system (movable though, is handled separately) - DisallowSwitchable = 0x0400,//User can not turn items from this system on/off. - DisallowController = 0x0800,//Custom controllers provided by this wont be present in the GUI - DisallowMovable = 0x1000,//Items from this systems are never movable - StartDisabled = 0x0010 - }; -public: //public instead of protected due to compilation problems on SLC3 - Q_DECLARE_FLAGS(SystemOptions, SystemOption) -protected: - //Call the following in constructor of a derived class. Do not delete the systems in the derived class. - void addSystem(IVP12DSystem*, const SystemOptions& options = AllowAll ); - - //////////////////// The following is for internal use /////////////////////// - - //Convenience so users dont need to cast themselves (needed due to private inheritance in IVP12DSystemSimple): - void addSystem(IVP12DSystemSimple*, const SystemOptions& options = AllowAll ); -public: - Type type() const { return TWODIMENSIONAL; }; - - void create(); - void systemRefreshed(IVP1System*); - void systemErased(IVP1System*); - virtual ~IVP12DStandardChannelWidget(); - virtual QByteArray saveState(); - virtual void restoreFromState(QByteArray); - -protected slots: - void showControlsForSystem(); - -private: - class Imp; - Imp * m_d; -private slots: - void toggleSystemActive(); - void setBackgroundColor(const QColor &); -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS(IVP12DStandardChannelWidget::SystemOptions) - -#endif diff --git a/GeoModelVisualization/VP1Base/VP1Base/IVP12DSystem.h b/GeoModelVisualization/VP1Base/VP1Base/IVP12DSystem.h deleted file mode 100644 index 27248e540c5cfca346bec004dbc036fb60b6fa7d..0000000000000000000000000000000000000000 --- a/GeoModelVisualization/VP1Base/VP1Base/IVP12DSystem.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -*/ - -///////////////////////////////////////////////////////////// -// // -// Header file for class IVP12DSystem // -// // -// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // -// // -// Initial version: April 2007 // -// // -///////////////////////////////////////////////////////////// - -#ifndef IVP12DSYSTEM_H -#define IVP12DSYSTEM_H - -#include "VP1Base/IVP1System.h" - -#include <QSet> - -class VP1GraphicsItemCollection; -class QGraphicsItem; - -class IVP12DSystem : public IVP1System { - - Q_OBJECT - -public: - - //////////////////////////////////////////////////////////////////////// - /////////// This is the interesting bit for those /////////// - /////////// who are deriving from, or using, this class... /////////// - //////////////////////////////////////////////////////////////////////// - - IVP12DSystem(const QString & name, const QString & information, const QString & contact_info); - - //Derived classes must call the following method exactly once on - //each item collection they provide: - void registerItemCollection(VP1GraphicsItemCollection*); - - //Reimplement if you need to catch user picks, selections or events (you need to enable the item collections for this!): - - virtual void itemPicked(VP1GraphicsItemCollection*,QGraphicsItem*); - virtual void itemGotEvent(VP1GraphicsItemCollection*,QGraphicsItem*,QEvent*); - virtual void selectionChanged(VP1GraphicsItemCollection*,QList<QGraphicsItem*>); - - //This is for use by the channels: - QSet<VP1GraphicsItemCollection*> getItemCollections(); - - //////////////////////////////////////////////////////////////////////// - //////////// The rest of this file is just internal stuff //////////// - //////////// - dont worry about it - //////////// - //////////////////////////////////////////////////////////////////////// - - virtual ~IVP12DSystem(); - -signals: - void itemFromSystemSelected();//Should be emitted whenever item in this system is selected (mainly to give channel chance to show the system controller) - -private: - IVP12DSystem( const IVP12DSystem & ); - IVP12DSystem & operator= ( const IVP12DSystem & ); - class Imp; - Imp * m_d; - -private slots: - void itemPickedPrivate(QGraphicsItem*); - void itemGotEventPrivate(QGraphicsItem*,QEvent*); - void selectionChangedPrivate(QList<QGraphicsItem*>); -}; - -#endif diff --git a/GeoModelVisualization/VP1Base/VP1Base/IVP12DSystemSimple.h b/GeoModelVisualization/VP1Base/VP1Base/IVP12DSystemSimple.h deleted file mode 100644 index 01eb22002cf9472169c5ce04ee840d3c63d40285..0000000000000000000000000000000000000000 --- a/GeoModelVisualization/VP1Base/VP1Base/IVP12DSystemSimple.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -*/ - -///////////////////////////////////////////////////////////// -// // -// Header file for class IVP12DSystemSimple // -// // -// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // -// // -// Initial version: April 2007 // -// // -///////////////////////////////////////////////////////////// - -#ifndef IVP12DSYSTEMSIMPLE_H -#define IVP12DSYSTEMSIMPLE_H - -#include "VP1Base/IVP12DSystem.h" - -class VP1GraphicsItemCollection; - -class IVP12DSystemSimple : public IVP12DSystem { - - Q_OBJECT - -public: - - //////////////////////////////////////////////////////////////////////// - ////////////// This is the interesting bit for those ////////////// - ////////////// who are deriving from this class... ////////////// - //////////////////////////////////////////////////////////////////////// - - IVP12DSystemSimple(const QString & name, const QString & information, const QString & contact_info); - - virtual void systemcreate(StoreGateSvc* detstore);//Optional. - - //If you need a controller - create it and return it from a reimplementation of this method (it will only be called once). - virtual QWidget * buildController(); - - //If some items should be visible for the entire run, reimplement: - virtual void buildPermanentItemCollection(StoreGateSvc* detstore,VP1GraphicsItemCollection*); - - //Reimplement and add the items for a given event, based on the contents of storegate: - virtual void buildEventItemCollection(StoreGateSvc *sg, VP1GraphicsItemCollection*); - - void updateGUI();//Call this occasionally in buildEventSceneGraph(...) to avoid GUI freezing. - - virtual void systemerase();//Optional - for erasing maps etc. with event data. - - virtual void systemuncreate();//Optional. - - //////////////////////////////////////////////////////////////////////// - //////////// The rest of this file is just internal stuff //////////// - //////////// - dont worry about it - //////////// - //////////////////////////////////////////////////////////////////////// - - virtual ~IVP12DSystemSimple(); -private: - IVP12DSystemSimple( const IVP12DSystemSimple & ); - IVP12DSystemSimple & operator= ( const IVP12DSystemSimple & ); - class Imp; - Imp * m_d; - void create(StoreGateSvc* detstore); - void refresh(StoreGateSvc* storegate); - void erase(); - void uncreate(); -}; - -/////////// Inlines ///////////// -inline void IVP12DSystemSimple::updateGUI() { IVP12DSystem::updateGUI(); } - - -#endif diff --git a/GeoModelVisualization/VP1Base/VP1Base/IVP1ChannelWidgetFactory.h b/GeoModelVisualization/VP1Base/VP1Base/IVP1ChannelWidgetFactory.h index dcde843453abdea2e5e55ca5134c656739866308..259d8cc327f9e7a0ab1a11c5a557c94dab1ec3b4 100644 --- a/GeoModelVisualization/VP1Base/VP1Base/IVP1ChannelWidgetFactory.h +++ b/GeoModelVisualization/VP1Base/VP1Base/IVP1ChannelWidgetFactory.h @@ -18,7 +18,6 @@ #include <QtPlugin> class QString; -class QStringList; class IVP1ChannelWidget; class IVP1ChannelWidgetFactory diff --git a/GeoModelVisualization/VP1Base/VP1Base/VP12DExaminerViewer.h b/GeoModelVisualization/VP1Base/VP1Base/VP12DExaminerViewer.h deleted file mode 100644 index 2b93ed308889da71f069e5f7413043bb655d4881..0000000000000000000000000000000000000000 --- a/GeoModelVisualization/VP1Base/VP1Base/VP12DExaminerViewer.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -*/ - -///////////////////////////////////////////////////////////// -// // -// Header file for class VP12DExaminerViewer // -// // -// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // -// // -// Initial version: April 2007 // -// Major update to support multiple views: July 2007 // -// // -///////////////////////////////////////////////////////////// - -#ifndef VP12DEXAMINERVIEWER_H -#define VP12DEXAMINERVIEWER_H - -#include <QList> -#include <QPair> -#include <QStringList> -#include <QWidget> - -class VP1GraphicsView; - -class VP12DExaminerViewer : public QWidget { - - Q_OBJECT - -public: - - //The choice of constructor will determine whether this view is in single or multi view mode: - - //An examinerviewer with just one VP1GraphicsView: - VP12DExaminerViewer(QWidget * parent = 0, Qt::WindowFlags f = 0); - //An examinerviewer with several VP1GraphicsView's. First argument is a list of view_id's and icon urls for the views: - VP12DExaminerViewer(const QList<QPair<QString,QString> >& views, QWidget * parent = 0, Qt::WindowFlags f = 0); - virtual ~VP12DExaminerViewer(); - - bool isSingleViewMode() const; - - VP1GraphicsView * view() const;//Returns the pointer to the view which is currently shown. - VP1GraphicsView * view(const QString& view_id) const;//Returns pointer to view with a given view_id (0 if view_id not found or single view mode). - QString currentView() const;//Only relevant in multiview mode (returns empty string otherwise) - - //These two return empty stringlists if we are in the mode with just one VP1GraphicsView: - QStringList viewIDs() const; - QList<QPair<QString,QString> > viewIDsAndIconUrls() const; - -public slots: - void setPickMode(); - void setChangeViewMode(); - void setSeekMode(); - void setShownView(QString);//Only relevant in multiview mode - -signals: - void currentViewAboutToChange(VP1GraphicsView*);//Emitted just before the view changes. Parameter is the view which will be shown. - void currentViewChanged();//Just after the view changed. - -private slots: - void changeViewButtonClicked(); -private: - VP12DExaminerViewer( const VP12DExaminerViewer & ); - VP12DExaminerViewer & operator= ( const VP12DExaminerViewer & ); - class Imp; - Imp * m_d; - -}; - -#endif diff --git a/GeoModelVisualization/VP1Base/VP1Base/VP1CollectionWidget.h b/GeoModelVisualization/VP1Base/VP1Base/VP1CollectionWidget.h index 7b40aa28e1487a20e98ba38b8e47d5d276658392..d42f35f9e038d0c83cac7f0bdf0265714bbef04e 100644 --- a/GeoModelVisualization/VP1Base/VP1Base/VP1CollectionWidget.h +++ b/GeoModelVisualization/VP1Base/VP1Base/VP1CollectionWidget.h @@ -20,6 +20,7 @@ #define VP1COLLECTIONWIDGET_H #include "VP1Base/VP1Collection.h" +#include "VP1Base/VP1StdCollection.h" #include "VP1Base/VP1HelperClassBase.h" #include <QWidget> @@ -27,7 +28,6 @@ #include <QString> -class VP1StdCollection; class VP1CollectionWidget : public QWidget, public VP1HelperClassBase { diff --git a/GeoModelVisualization/VP1Base/VP1Base/VP1GraphicsItemCollection.h b/GeoModelVisualization/VP1Base/VP1Base/VP1GraphicsItemCollection.h deleted file mode 100644 index ed6855c302b3a6f75efae2cdc19997b4d7400573..0000000000000000000000000000000000000000 --- a/GeoModelVisualization/VP1Base/VP1Base/VP1GraphicsItemCollection.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -*/ - -///////////////////////////////////////////////////////////// -// // -// Header file for class VP1GraphicsItemCollection // -// // -// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // -// // -// Initial version: April 2007 // -// // -///////////////////////////////////////////////////////////// - -#ifndef VP1GRAPHICSITEMCOLLECTION_H -#define VP1GRAPHICSITEMCOLLECTION_H - -//Policy: It is forbidden for systems/channels to install -// eventhandlers or to set flags on QGraphicsItems!!!!! -// -// Each item is marked as either ACTIVE or PASSIVE [+movable] -// (internally an ic knows whether it has any active items at all of -// course). An IC can be in exactly one of the following modes, -// governing how its active items respond (this state is set at -// initialisation by the system and is not changeable later - if so, -// warn if INACTIVE system has active elements and vice versa?): -// -// INERT, SINGLEPICKS, SINGLEEVENTS, SELECTIONS (+UNSET) -// -// It must be set BEFORE a scene is attached for the first time. -// -// Furthermore, each IC has a temporary ignore state, which makes it -// temporarily work (i.e. respond to questions such as "is this item -// presently active") just as if it was inert -// -// -// In graphicsview: Any click or event gets passed to the topmost -// active item in a non-inert system. -// -// If there was a previous selection: -// If the new item is not in the same IC as the previous selection: clear selection. -// Else: If shift was down: Add to selection. Else: Set selection to the new item. -// -// Future: Special selection tool which lets you draw a path and select anything inside it (needs to know which system it is selecting from) -// -// Any change of selection or occurrence of picks/events makes the GV ask the appropriate IC to emit a signal. - -#include <QObject> - -class VP1GraphicsView; -class QGraphicsItem; - -class VP1GraphicsItemCollection : public QObject { - - Q_OBJECT - -public: - - VP1GraphicsItemCollection( QObject * parent=0 ); - virtual ~VP1GraphicsItemCollection(); - - enum INTERACTIONMODE { INERT, SINGLEPICKS, EVENTS, SELECTIONS }; - void setInteractionMode( const INTERACTIONMODE& ); //Can only be called while not attached to a view. - //Default is INERT. - INTERACTIONMODE interactionMode() const; - - void addItem( QGraphicsItem*, const bool& active = false, const bool&movable=false ); - //Beware: All items added will be owned by this class - but if you call removeItem below, you will own them again. - - //The next methods returns false if the item has not been previously added to the collection: - bool setActive(QGraphicsItem*, const bool& active = true); - bool setMovable(QGraphicsItem* item, const bool& movable=true); - bool removeItem(QGraphicsItem*);//Does not delete item. - bool hasItem(QGraphicsItem*) const; - - void clear(const bool& deleteitems = true);//Removes and possibly deletes all items. - - //These two can be called from e.g. the systems to avoid updates during intensive work: - void detachFromView();//If was not attached, do nothing - void reattachToView();//Only does something if it has been previously attached. - bool isAttachedToView(); - - //These three gives the same answer irrespective of the temporary ignore state - int nItems() const; - int nActiveItems() const; - int nMovableItems() const; - //These two always returns 0 if there is a temporary ignore state: - int nPresentlyActiveItems() const; - int nPresentlyMovableItems() const; - - bool itemBelongsAndIsPresentlyActive(QGraphicsItem*) const; - -signals: - void itemPicked(QGraphicsItem*) const;//Emitted for active items when in SINGLEPICK mode. - void itemGotEvent(QGraphicsItem*,QEvent*) const;//Emitted for active items when in EVENTS mode. - void selectionChanged(QList<QGraphicsItem*>) const;//Emitted for active items when in SELECTIONS mode. - -private: - VP1GraphicsItemCollection( const VP1GraphicsItemCollection & ); - VP1GraphicsItemCollection & operator= ( const VP1GraphicsItemCollection & ); - class Imp; - Imp * m_d; -private: - friend class VP1GraphicsView; - void attachToView(VP1GraphicsView*); - void real_detachFromView(); - void setTemporaryIgnoreInteractions( const bool& ); - void setTemporaryIgnoreMovable( const bool& ); - void itemPickedPrivate(QGraphicsItem*) const; - void itemGotEventPrivate(QGraphicsItem*,QEvent*) const; - void selectionChangedPrivate(QList<QGraphicsItem*>) const; -}; - -#endif diff --git a/GeoModelVisualization/VP1Base/VP1Base/VP1GraphicsView.h b/GeoModelVisualization/VP1Base/VP1Base/VP1GraphicsView.h deleted file mode 100644 index 36515a7c27799a115ad4e75d367ef4c0464b707a..0000000000000000000000000000000000000000 --- a/GeoModelVisualization/VP1Base/VP1Base/VP1GraphicsView.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -*/ - -///////////////////////////////////////////////////////////// -// // -// Header file for class VP1GraphicsView // -// // -// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // -// // -// Initial version: April 2007 // -// // -///////////////////////////////////////////////////////////// - -#ifndef VP1GRAPHICSVIEW_H -#define VP1GRAPHICSVIEW_H - -#include <QGraphicsView> - -class VP1GraphicsItemCollection; - -class VP1GraphicsView : public QGraphicsView { - - Q_OBJECT - -public: - - //////////////////////////////////////////////////////////////////////// - /////////////// This is the interesting bit for those //////////////// - /////////////// who are using this class... //////////////// - //////////////////////////////////////////////////////////////////////// - - VP1GraphicsView ( QWidget * parent = 0 ); - VP1GraphicsView ( QGraphicsScene * scene, QWidget * parent = 0 ); - - //Get interaction mode: - enum Mode { PICK, CHANGEVIEW, SEEK, DRAGZOOM, DRAGZOOMHOLD }; - Mode mode() const; - -public slots: - - //What collections to show: - void addItemCollection(VP1GraphicsItemCollection*); - void removeItemCollection(VP1GraphicsItemCollection*); - - //Set interaction mode for the view: - void setMode(const Mode&); - - //Potentially limit the interactive capabilities of given itemcollections: - void setDisallowInteractions(VP1GraphicsItemCollection*, const bool& disallow=true );//If true, the ic will act as INERT - void setDisallowMovable(VP1GraphicsItemCollection*, const bool& disallow=true );//If true, items will never be movable. - - //Zoom: - void scaleView(qreal scaleFactor); - void fitViewToContents(); - void viewHome(); - void setHome(); - - //Animated zoom: - void initiateAnimatedZoomTo(QRectF); - void setAnimatedZoomSteps(int); - void setAnimatedZoomTime(double);//ms - void setZoomFactorOnSeek(double); - void abortZoomAnimation(); - void seekToPoint(QPointF); - - //Selections: - void clearSelections(); - - //Print: - void print(); - void saveImage(); - - //////////////////////////////////////////////////////////////////////// - //////////// The rest of this file is just internal stuff //////////// - //////////// - dont worry about it - //////////// - //////////////////////////////////////////////////////////////////////// - -public: - virtual ~VP1GraphicsView(); - -protected: - void keyPressEvent(QKeyEvent *); - void wheelEvent(QWheelEvent *); - void mouseDoubleClickEvent(QMouseEvent * event); - void mousePressEvent(QMouseEvent *); - void mouseReleaseEvent(QMouseEvent *); - void mouseMoveEvent(QMouseEvent *); - void drawItems(QPainter *painter, int numItems, - QGraphicsItem *items[], - const QStyleOptionGraphicsItem options[]); - void drawForeground ( QPainter * painter, const QRectF & rect ); -private: - - class Imp; - Imp * m_d; - class HighLightItem; - friend class HighLightItem; - void emitSelectionChanged(VP1GraphicsItemCollection*); - -private slots: - void updateZoomAnimation(); -}; - -#endif diff --git a/GeoModelVisualization/VP1Base/VP1Base/VP1TabWidget.h b/GeoModelVisualization/VP1Base/VP1Base/VP1TabWidget.h index 072f011b9144012d9f859ebfc9c959810ec2452d..29b47160dc448a34765690f5f8204857e097d51c 100644 --- a/GeoModelVisualization/VP1Base/VP1Base/VP1TabWidget.h +++ b/GeoModelVisualization/VP1Base/VP1Base/VP1TabWidget.h @@ -52,7 +52,7 @@ class VP1TabWidget : public QTabWidget VP1TabBar* getVP1TabBar();//Added by TK. - explicit VP1TabWidget( QWidget *parent = 0, Qt::WindowFlags flags = 0 ); + explicit VP1TabWidget( QWidget *parent = 0, Qt::WindowFlags flags = Qt::Widget ); virtual ~VP1TabWidget(); diff --git a/GeoModelVisualization/VP1Base/src/IVP12DDetViewsChannelWidget.cxx b/GeoModelVisualization/VP1Base/src/IVP12DDetViewsChannelWidget.cxx deleted file mode 100644 index c36401a592b0e728a267ed83e4b973e1ebc62d50..0000000000000000000000000000000000000000 --- a/GeoModelVisualization/VP1Base/src/IVP12DDetViewsChannelWidget.cxx +++ /dev/null @@ -1,387 +0,0 @@ -/* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -*/ - -///////////////////////////////////////////////////////////// -// // -// Implementation of class IVP12DDetViewsChannelWidget // -// // -// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // -// // -// Initial version: July 2007 // -// // -///////////////////////////////////////////////////////////// - -#include "VP1Base/IVP12DDetViewsChannelWidget.h" - -#include "VP1Base/IVP12DSystem.h" -#include "VP1Base/IVP12DDetViewsSystem.h" -#include "VP1Base/VP1Msg.h" - -#include "VP1Base/VP1GraphicsItemCollection.h" -#include "VP1Base/VP1GraphicsView.h" -#include "VP1Base/VP12DExaminerViewer.h" -#include "VP1Base/VP1TabWidget.h" - -#include "VP1Base/VP1ControllerHelper.h" -#include "VP1Base/VP1ColorSelectButton.h" - -#include <QCheckBox> -#include <QGraphicsScene> -#include <QVBoxLayout> -#include <QByteArray> -#include <QBuffer> -#include <QMap> - -#include <cassert> - - -class IVP12DDetViewsChannelWidget::Imp { -public: - IVP12DDetViewsChannelWidget*channel; - VP1GraphicsView * view_xy; - VP1GraphicsView * view_rz; - bool first; - - QMap<IVP12DSystem*,QSet<VP1GraphicsItemCollection*> > system2itemcols; - - QMap<QCheckBox*,IVP1System*> checkbox2system; - QList<IVP1System*> systemsAllowedControllers; - QList<QPair<IVP1System*,bool> > system2switchable; - QMap<IVP1System*,bool> system2startdisabled; - - void updateSystemState(QCheckBox*); - - QMap<IVP1System*,QWidget*> sys2tabpage; - VP1TabWidget*tabwidget; - - VP1ColorSelectButton * colorselectbutton; -}; - -//___________________________________________________________________________ -IVP12DDetViewsChannelWidget::IVP12DDetViewsChannelWidget(const QString & name, const QString & information, const QString & contact_info) - : IVP1ChannelWidget(name,information,contact_info), m_d(new Imp()) -{ - m_d->channel=this; - m_d->first=true; - setMinimumSize(150,240);//minimum y size is to avoid absurd squeezing of buttons. - - //Tight layout: - QVBoxLayout * vboxLayout = new QVBoxLayout(this); - vboxLayout->setSpacing(0); - vboxLayout->setMargin(0); - - //Setup examiner viewer: - QList<QPair<QString,QString> > views; - views << QPair<QString,QString>("X-Y",":/icons/icons/xy.png"); - views << QPair<QString,QString>("R-Z",":/icons/icons/rz.png"); - VP12DExaminerViewer * examiner = new VP12DExaminerViewer(views, this); - - vboxLayout->addWidget(examiner); - - //Get pointers to the different views: - m_d->view_xy = examiner->view("X-Y"); - m_d->view_rz = examiner->view("R-Z"); - assert(m_d->view_xy&&m_d->view_rz); - - m_d->tabwidget = 0; - m_d->colorselectbutton = 0; -} - -//___________________________________________________________________________ -IVP12DDetViewsChannelWidget::~IVP12DDetViewsChannelWidget() -{ - delete m_d; -} - -//___________________________________________________________________________ -void IVP12DDetViewsChannelWidget::addSystem( IVP12DDetViewsSystem*system, double /*zfactor*/, const SystemOptions& options ) { - - //Apart from the attachment of ic's to view's, this method is quite similar to the ones in addGeneralSystem - bool handleSelections = ! (options & DisallowSelections); - bool switchable = ! (options & DisallowSwitchable); - bool allowController = ! (options & DisallowController); - bool allowMovable = ! (options & DisallowMovable); - bool startDisabled = (options & StartDisabled); - - registerSystem(system); - - //Fixme: Attach to the relevant view instead. - assert(!m_d->system2itemcols.contains(system)); - - m_d->system2itemcols.insert(system,system->getItemCollections_XY()+system->getItemCollections_RZ()); - - foreach (VP1GraphicsItemCollection*ic,system->getItemCollections_XY()) - m_d->view_xy->addItemCollection(ic); - foreach (VP1GraphicsItemCollection*ic,system->getItemCollections_RZ()) - m_d->view_rz->addItemCollection(ic); - - foreach (VP1GraphicsItemCollection* ic,system->getItemCollections_XY()) - m_d->view_xy->setDisallowInteractions(ic, !handleSelections ); - foreach (VP1GraphicsItemCollection* ic,system->getItemCollections_RZ()) - m_d->view_rz->setDisallowInteractions(ic, !handleSelections ); - - foreach (VP1GraphicsItemCollection* ic,system->getItemCollections_XY()) - m_d->view_xy->setDisallowMovable(ic, !allowMovable ); - foreach (VP1GraphicsItemCollection* ic,system->getItemCollections_RZ()) - m_d->view_rz->setDisallowMovable(ic, !allowMovable ); - - m_d->system2switchable << QPair<IVP1System*,bool>(system,switchable); - - assert(!m_d->system2startdisabled.contains(system)); - m_d->system2startdisabled.insert(system,startDisabled); - assert(m_d->system2startdisabled.contains(system)); - - if (allowController) { - m_d->systemsAllowedControllers << system; - connect(system,SIGNAL(itemFromSystemSelected()),this,SLOT(showControlsForSystem())); - } - -} - -//___________________________________________________________________________ -void IVP12DDetViewsChannelWidget::create() { - //Fixme: Less code should be replicated here and in IVP12DStandardChannelWidget+IVP13DStandardChannelWidget. - - //Set up the controller. - registerController(VP1ControllerHelper::compositionController( m_d->systemsAllowedControllers, - m_d->sys2tabpage,m_d->tabwidget, - m_d->system2switchable, - m_d->checkbox2system, - m_d->colorselectbutton )); - connect(m_d->colorselectbutton,SIGNAL(colorChanged(const QColor&)),this,SLOT(setBackgroundColor(const QColor&))); - m_d->system2switchable.clear(); - - QMapIterator<QCheckBox*,IVP1System*> it(m_d->checkbox2system); - while (it.hasNext()) { - it.next(); - - assert(m_d->system2startdisabled.contains(it.value())); - if (m_d->system2startdisabled[it.value()]) { - it.key()->setChecked(false); - m_d->updateSystemState(it.key()); - } - - connect(it.key(),SIGNAL(toggled(bool)),this,SLOT(toggleSystemActive())); - } -} - - -//___________________________________________________________________________ -void IVP12DDetViewsChannelWidget::systemRefreshed(IVP1System*) { - if (m_d->first) { - //This is not perfect, but usually it gives acceptable results. - //Todo: An improvement would be to keep track of the first time - //separately, and then only call fitViewToContents on the views - //where this system provides collections. - m_d->view_xy->fitViewToContents(); - m_d->view_rz->fitViewToContents(); - m_d->first=false; - } -} - -//___________________________________________________________________________ -void IVP12DDetViewsChannelWidget::systemErased(IVP1System*) { - m_d->view_xy->clearSelections(); - m_d->view_rz->clearSelections(); -} - -//___________________________________________________________________________ -void IVP12DDetViewsChannelWidget::toggleSystemActive() -{ - QCheckBox * cb = static_cast<QCheckBox*>(sender()); assert(cb); - m_d->updateSystemState(cb); -} - -//___________________________________________________________________________ -void IVP12DDetViewsChannelWidget::Imp::updateSystemState(QCheckBox* cb) -{ - assert(checkbox2system.contains(cb)); - IVP12DSystem*sys = static_cast<IVP12DSystem*>(checkbox2system.value(cb)); assert(sys); - - assert(system2itemcols.contains(sys)); - if (cb->isChecked()) { - channel->turnOn(sys); - foreach(VP1GraphicsItemCollection*ic,system2itemcols.value(sys)) { - ic->reattachToView(); - } - if (tabwidget&&sys2tabpage.contains(sys)) { - int sysindex = systemsAllowedControllers.indexOf(sys); - if (sysindex>=0) { - IVP1System*nextsystem(0); - for (int i=sysindex+1;i<systemsAllowedControllers.count();++i) { - //Loop through latter systems with controllers in order and - //find the first of those which currently has an active - //controller: - IVP1System* testsys = systemsAllowedControllers.at(i); - if (sys2tabpage.contains(testsys)&&tabwidget->indexOf(sys2tabpage[testsys])>-1) { - nextsystem=testsys; - break; - } - } - //put before tab of "nextsystem" (or at the end if no nextsystem): - int index = (nextsystem?tabwidget->indexOf(sys2tabpage[nextsystem]):99999); - tabwidget->insertTab(index,sys2tabpage[sys],sys->name()); - int index2 = tabwidget->indexOf(sys2tabpage[sys]); - if (index2!=-1) { - tabwidget->setTabEnabled(index2,true); - } - } - } - } else { - //Fixme: if system being turned off has selections, we should deselect!! - channel->turnOff(sys,false); - foreach(VP1GraphicsItemCollection*ic,system2itemcols.value(sys)) { - ic->detachFromView(); - } - if (tabwidget&&sys2tabpage.contains(sys)) { - int index = tabwidget->indexOf(sys2tabpage[sys]); - if (index!=-1) { - tabwidget->setTabEnabled(index,false); - tabwidget->removeTab(index); - } - } - } - - view_xy->scene()->update(); - view_rz->scene()->update(); - -} - -//___________________________________________________________________________ -void IVP12DDetViewsChannelWidget::addGeneralSystem(IVP12DSystem*, const PROJECTION& /*projection*/, double /*zfactor*/, const SystemOptions& /*options*/ ) -{ - message("IVP12DDetViewsChannelWidget::addGeneralSystem ERROR: Method not implemented yet!!");//fixme -} - -//___________________________________________________________________________ -void IVP12DDetViewsChannelWidget::setBackgroundColor(const QColor & col) -{ - if (!col.isValid()) - return; - m_d->view_xy->setBackgroundBrush(col); - m_d->view_rz->setBackgroundBrush(col); -} - -//___________________________________________________________________________ -void IVP12DDetViewsChannelWidget::showControlsForSystem( ) -{ - if (!m_d->tabwidget) - return; - IVP1System * sys = static_cast<IVP1System*>(sender()); - if (!sys) { - message("showControlsForSystem Error: Unable to determine system identity."); - return; - } - if (!m_d->sys2tabpage.contains(sys)) { - //Dont send warning here. The system in question might simply not have a controller! - return; - } - - int index = m_d->tabwidget->indexOf(m_d->sys2tabpage[sys]); - if (index<0||!m_d->tabwidget->isTabEnabled(index)) { - message("Warning: Asked to show controller for a disabled system. Surely you jest?"); - return; - } - m_d->tabwidget->setCurrentIndex(index); -} - -//___________________________________________________________________________ -QByteArray IVP12DDetViewsChannelWidget::saveState() -{ - VP1Msg::messageVerbose("IVP12DDetViewsChannelWidget::saveState"); - // ===> Setup stream writing to a byteArray: - QByteArray byteArray; - QBuffer buffer(&byteArray); - buffer.open(QIODevice::WriteOnly); - QDataStream out(&buffer); - - // ===> Write Data: - - //Version & base state: - out << (qint32)0; //version - out << IVP1ChannelWidget::saveState();//Always include state info from the base class. - - //Background color: - out << m_d->colorselectbutton->color(); - - //Systems turned on/off: - //Fixme: Make sure that if you have two copies of the same system, - //that the text in the checkbox gets appended some stuff like [1], - //[2], etc., so that the strings used here will be unique. - QMap<QString, bool> sysname2turnedon; - QMap<QCheckBox*,IVP1System*>::const_iterator it = m_d->checkbox2system.constBegin(); - while (it != m_d->checkbox2system.constEnd()) { - sysname2turnedon.insert(it.key()->text(),it.key()->isChecked()); - ++it; - } - - out << sysname2turnedon; - - //Current system tab: - if (m_d->tabwidget) - out << m_d->tabwidget->tabText(m_d->tabwidget->currentIndex()); - else - out << QString(""); - - // ===> Finish up: - buffer.close(); - return byteArray; -} - -//___________________________________________________________________________ -void IVP12DDetViewsChannelWidget::restoreFromState(QByteArray ba) -{ - VP1Msg::messageVerbose("IVP12DDetViewsChannelWidget::restoreFromState"); - - // ===> Setup stream for getting the contents of the byteArray: - QBuffer buffer(&ba); - buffer.open(QIODevice::ReadOnly); - QDataStream state(&buffer); - // ===> Check version and pass on state info to base class: - qint32 version; - state >> version; - if (version!=0) { - message("Warning: State data in .vp1 file is in wrong format - ignoring!"); - return; - } - QByteArray basestate; - state >> basestate; - IVP1ChannelWidget::restoreFromState(basestate); - // ===> Decode the state info: - - QColor bgdcol; - state >> bgdcol; - if (bgdcol!=m_d->colorselectbutton->color()) - m_d->colorselectbutton->setColor(bgdcol); - setBackgroundColor(bgdcol); - - //Switch systems on/off: - QMap<QString, bool> sysname2turnedon; - state >> sysname2turnedon; - QMap<QCheckBox*,IVP1System*>::const_iterator it = m_d->checkbox2system.constBegin(); - while (it != m_d->checkbox2system.constEnd()) { - if (sysname2turnedon.contains(it.key()->text())) { - if (sysname2turnedon[it.key()->text()]!=it.key()->isChecked()) - it.key()->setChecked(sysname2turnedon[it.key()->text()]); - } else { - message("Warning: Config data does not contain information about switched state of subsystem '"+it.key()->text()+"'"); - } - ++it; - } - - //Current system tab - QString tabname; - state >> tabname; - if (m_d->tabwidget) { - for (int i = 0; i < m_d->tabwidget->count(); ++i) { - if (m_d->tabwidget->tabText(i) == tabname) { - m_d->tabwidget->setCurrentIndex(i); - break; - } - } - } - - // ===> Finish up: - buffer.close(); -} diff --git a/GeoModelVisualization/VP1Base/src/IVP12DDetViewsSystem.cxx b/GeoModelVisualization/VP1Base/src/IVP12DDetViewsSystem.cxx deleted file mode 100644 index 70de6fe20a8771fa4a68f3398c48f5366b0031df..0000000000000000000000000000000000000000 --- a/GeoModelVisualization/VP1Base/src/IVP12DDetViewsSystem.cxx +++ /dev/null @@ -1,172 +0,0 @@ -/* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -*/ - -///////////////////////////////////////////////////////////// -// // -// Implementation of class IVP12DDetViewsSystem // -// // -// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // -// // -// Initial version: July 2007 // -// // -///////////////////////////////////////////////////////////// - -#include "VP1Base/IVP12DDetViewsSystem.h" -#include "VP1Base/VP1GraphicsItemCollection.h" -#include <cassert> - -void IVP12DDetViewsSystem::systemcreate(StoreGateSvc*) {} -QWidget * IVP12DDetViewsSystem::buildController() { return 0; } -void IVP12DDetViewsSystem::buildPermanentItemCollections(StoreGateSvc*,VP1GraphicsItemCollection*, - VP1GraphicsItemCollection*){} -void IVP12DDetViewsSystem::buildEventItemCollections(StoreGateSvc*,VP1GraphicsItemCollection*, - VP1GraphicsItemCollection*){} -void IVP12DDetViewsSystem::systemuncreate() {} -void IVP12DDetViewsSystem::systemerase() {} - -//____________________________________________________________________ -class IVP12DDetViewsSystem::Imp { -public: - VP1GraphicsItemCollection* itemcollectionPermanent_xy; - VP1GraphicsItemCollection* itemcollectionPermanent_rz; - VP1GraphicsItemCollection* itemcollectionEvent_xy; - VP1GraphicsItemCollection* itemcollectionEvent_rz; - bool wasrefreshed; - bool wascreated; -}; - -//____________________________________________________________________ -IVP12DDetViewsSystem::IVP12DDetViewsSystem(const QString & name, const QString & information, const QString & contact_info) - : IVP12DSystem(name,information,contact_info), m_d(new Imp) -{ - m_d->itemcollectionPermanent_xy = new VP1GraphicsItemCollection(this); - m_d->itemcollectionPermanent_rz = new VP1GraphicsItemCollection(this); - m_d->itemcollectionEvent_xy = new VP1GraphicsItemCollection(this); - m_d->itemcollectionEvent_rz = new VP1GraphicsItemCollection(this); - - registerItemCollection(m_d->itemcollectionPermanent_xy); - registerItemCollection(m_d->itemcollectionPermanent_rz); - registerItemCollection(m_d->itemcollectionEvent_xy); - registerItemCollection(m_d->itemcollectionEvent_rz); - - m_d->wasrefreshed=false; - m_d->wascreated=false; -} - -//____________________________________________________________________ -IVP12DDetViewsSystem::~IVP12DDetViewsSystem() -{ - delete m_d; m_d=0; -} - -//____________________________________________________________________ -void IVP12DDetViewsSystem::create(StoreGateSvc* detstore) -{ - assert(!m_d->wascreated); - systemcreate(detstore); - - QWidget * controller = buildController(); - if (controller) - registerController(controller); - - bool hasview_xy = m_d->itemcollectionPermanent_xy->isAttachedToView(); - if (hasview_xy) - m_d->itemcollectionPermanent_xy->detachFromView(); - bool hasview_rz = m_d->itemcollectionPermanent_rz->isAttachedToView(); - if (hasview_rz) - m_d->itemcollectionPermanent_rz->detachFromView(); - - buildPermanentItemCollections(detstore, - m_d->itemcollectionPermanent_xy, - m_d->itemcollectionPermanent_rz ); - - if (hasview_xy) - m_d->itemcollectionPermanent_xy->reattachToView(); - if (hasview_rz) - m_d->itemcollectionPermanent_rz->reattachToView(); - - m_d->wascreated=true; -} - -//____________________________________________________________________ -void IVP12DDetViewsSystem::refresh(StoreGateSvc* sg) -{ - assert(m_d->wascreated); - assert(!m_d->wasrefreshed); - - bool hasview_xy = m_d->itemcollectionEvent_xy->isAttachedToView(); - if (hasview_xy) - m_d->itemcollectionEvent_xy->detachFromView(); - updateGUI(); - bool hasview_rz = m_d->itemcollectionEvent_rz->isAttachedToView(); - if (hasview_rz) - m_d->itemcollectionEvent_rz->detachFromView(); - updateGUI(); - - buildEventItemCollections( sg, - m_d->itemcollectionEvent_xy, - m_d->itemcollectionEvent_rz ); - - updateGUI(); - if (hasview_xy) - m_d->itemcollectionEvent_xy->reattachToView(); - updateGUI(); - if (hasview_rz) - m_d->itemcollectionEvent_rz->reattachToView(); - - m_d->wasrefreshed=true; -} - -//____________________________________________________________________ -void IVP12DDetViewsSystem::erase() -{ - assert(m_d->wascreated); - assert(m_d->wasrefreshed); - systemerase(); - m_d->itemcollectionEvent_xy->clear(); - m_d->itemcollectionEvent_rz->clear(); - m_d->wasrefreshed=false; -} - -//____________________________________________________________________ -void IVP12DDetViewsSystem::uncreate() -{ - messageDebug("uncreate()..."); - - assert(m_d->wascreated); - assert(!m_d->wasrefreshed); - - if (m_d->itemcollectionEvent_xy->isAttachedToView()) - m_d->itemcollectionEvent_xy->detachFromView(); - if (m_d->itemcollectionEvent_rz->isAttachedToView()) - m_d->itemcollectionEvent_rz->detachFromView(); - - if (m_d->itemcollectionPermanent_xy->isAttachedToView()) - m_d->itemcollectionPermanent_xy->detachFromView(); - if (m_d->itemcollectionPermanent_rz->isAttachedToView()) - m_d->itemcollectionPermanent_rz->detachFromView(); - - systemuncreate(); - m_d->itemcollectionPermanent_xy->clear(); - m_d->itemcollectionPermanent_rz->clear(); - m_d->wascreated=false; -} - -//____________________________________________________________________ -QSet<VP1GraphicsItemCollection*> IVP12DDetViewsSystem::getItemCollections_XY() const -{ - QSet<VP1GraphicsItemCollection*> l; - l << m_d->itemcollectionPermanent_xy; - l << m_d->itemcollectionEvent_xy; - return l; -} - -//____________________________________________________________________ -QSet<VP1GraphicsItemCollection*> IVP12DDetViewsSystem::getItemCollections_RZ() const -{ - QSet<VP1GraphicsItemCollection*> l; - l << m_d->itemcollectionPermanent_rz; - l << m_d->itemcollectionEvent_rz; - return l; -} diff --git a/GeoModelVisualization/VP1Base/src/IVP12DStandardChannelWidget.cxx b/GeoModelVisualization/VP1Base/src/IVP12DStandardChannelWidget.cxx deleted file mode 100644 index 3be196558f6ed3df92845e041b1340fa6123a8ab..0000000000000000000000000000000000000000 --- a/GeoModelVisualization/VP1Base/src/IVP12DStandardChannelWidget.cxx +++ /dev/null @@ -1,359 +0,0 @@ -/* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -*/ - -///////////////////////////////////////////////////////////// -// // -// Implementation of class IVP12DStandardChannelWidget // -// // -// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // -// // -// Initial version: April 2007 // -// // -///////////////////////////////////////////////////////////// - -#include "VP1Base/IVP12DStandardChannelWidget.h" -#include "VP1Base/IVP12DSystem.h" -#include "VP1Base/IVP12DSystemSimple.h" -#include "VP1Base/VP1GraphicsItemCollection.h" -#include "VP1Base/VP1GraphicsView.h" -#include "VP1Base/VP12DExaminerViewer.h" -#include "VP1Base/VP1TabWidget.h" -#include "VP1Base/VP1ControllerHelper.h" -#include "VP1Base/VP1ColorSelectButton.h" -#include "VP1Base/VP1Msg.h" - -#include <QVBoxLayout> -#include <QGraphicsScene> -#include <QCheckBox> -#include <QMap> -#include <QBuffer> -#include <QByteArray> - - -#include <cassert> - - -class IVP12DStandardChannelWidget::Imp { -public: - IVP12DStandardChannelWidget*channel; - VP1GraphicsView * view; - bool first; - QMap<IVP12DSystem*,QSet<VP1GraphicsItemCollection*> > system2itemcols; - - QMap<QCheckBox*,IVP1System*> checkbox2system; - QList<IVP1System*> systemsAllowedControllers; - QList<QPair<IVP1System*,bool> > system2switchable; - QMap<IVP1System*,bool> system2startdisabled; - - void updateSystemState(QCheckBox*); - - QMap<IVP1System*,QWidget*> sys2tabpage; - VP1TabWidget*tabwidget; - - VP1ColorSelectButton * colorselectbutton; - -}; - -//___________________________________________________________________________ -IVP12DStandardChannelWidget::IVP12DStandardChannelWidget(const QString & name, const QString & information, const QString & contact_info) - : IVP1ChannelWidget(name,information,contact_info), m_d(new Imp()) -{ - m_d->channel=this; - m_d->first=true; - setMinimumSize(150,240);//minimum y size is to avoid absurd squeezing of buttons. - - QVBoxLayout * vboxLayout = new QVBoxLayout(this); - vboxLayout->setSpacing(0); - vboxLayout->setMargin(0); - VP12DExaminerViewer * examiner = new VP12DExaminerViewer(this); - vboxLayout->addWidget(examiner); - m_d->colorselectbutton = 0; - - m_d->view = examiner->view(); - - m_d->tabwidget = 0; -} - -//___________________________________________________________________________ -IVP12DStandardChannelWidget::~IVP12DStandardChannelWidget() -{ - delete m_d; -} - -//___________________________________________________________________________ -void IVP12DStandardChannelWidget::addSystem( IVP12DSystem*system, const SystemOptions& options ) { - - bool handleSelections = ! (options & DisallowSelections); - bool switchable = ! (options & DisallowSwitchable); - bool allowController = ! (options & DisallowController); - bool allowMovable = ! (options & DisallowMovable); - bool startDisabled = (options & StartDisabled); - - registerSystem(system); - - assert(!m_d->system2itemcols.contains(system)); - m_d->system2itemcols.insert(system,system->getItemCollections()); - foreach (VP1GraphicsItemCollection*ic,system->getItemCollections()) { - m_d->view->addItemCollection(ic); - } - - foreach (VP1GraphicsItemCollection* ic,system->getItemCollections()){ - m_d->view->setDisallowInteractions(ic, !handleSelections ); - } - foreach (VP1GraphicsItemCollection* ic,system->getItemCollections()){ - m_d->view->setDisallowMovable(ic, !allowMovable ); - } - - m_d->system2switchable << QPair<IVP1System*,bool>(system,switchable); - - assert(!m_d->system2startdisabled.contains(system)); - m_d->system2startdisabled.insert(system,startDisabled); - assert(m_d->system2startdisabled.contains(system)); - - if (allowController) { - m_d->systemsAllowedControllers << system; - connect(system,SIGNAL(itemFromSystemSelected()),this,SLOT(showControlsForSystem())); - } -} - -//___________________________________________________________________________ -void IVP12DStandardChannelWidget::create() { - //Fixme: Less code should be replicated here and in IVP13DStandardChannelWidget+IVP12DDetViewsChannelWidget - - //Set up the controller. - registerController(VP1ControllerHelper::compositionController( m_d->systemsAllowedControllers, - m_d->sys2tabpage,m_d->tabwidget, - m_d->system2switchable, - m_d->checkbox2system, - m_d->colorselectbutton )); - connect(m_d->colorselectbutton,SIGNAL(colorChanged(const QColor&)),this,SLOT(setBackgroundColor(const QColor&))); - m_d->system2switchable.clear(); - - QMapIterator<QCheckBox*,IVP1System*> it(m_d->checkbox2system); - while (it.hasNext()) { - it.next(); - - assert(m_d->system2startdisabled.contains(it.value())); - if (m_d->system2startdisabled[it.value()]) { - it.key()->setChecked(false); - m_d->updateSystemState(it.key()); - } - - connect(it.key(),SIGNAL(toggled(bool)),this,SLOT(toggleSystemActive())); - } -} - - -//___________________________________________________________________________ -void IVP12DStandardChannelWidget::systemRefreshed(IVP1System*) { - if (m_d->first) { - m_d->view->fitViewToContents(); - m_d->first=false; - } -} - -//___________________________________________________________________________ -void IVP12DStandardChannelWidget::systemErased(IVP1System*) { - m_d->view->clearSelections(); -} - -//___________________________________________________________________________ -void IVP12DStandardChannelWidget::toggleSystemActive() -{ - QCheckBox * cb = static_cast<QCheckBox*>(sender()); assert(cb); - m_d->updateSystemState(cb); -} - -//___________________________________________________________________________ -void IVP12DStandardChannelWidget::Imp::updateSystemState(QCheckBox* cb) -{ - assert(checkbox2system.contains(cb)); - IVP12DSystem*sys = static_cast<IVP12DSystem*>(checkbox2system.value(cb)); assert(sys); - - assert(system2itemcols.contains(sys)); - if (cb->isChecked()) { - channel->turnOn(sys); - foreach(VP1GraphicsItemCollection*ic,system2itemcols.value(sys)) { - ic->reattachToView(); - } - if (tabwidget&&sys2tabpage.contains(sys)) { - int sysindex = systemsAllowedControllers.indexOf(sys); - if (sysindex>=0) { - IVP1System*nextsystem(0); - for (int i=sysindex+1;i<systemsAllowedControllers.count();++i) { - //Loop through latter systems with controllers in order and - //find the first of those which currently has an active - //controller: - IVP1System* testsys = systemsAllowedControllers.at(i); - if (sys2tabpage.contains(testsys)&&tabwidget->indexOf(sys2tabpage[testsys])>-1) { - nextsystem=testsys; - break; - } - } - //put before tab of "nextsystem" (or at the end if no nextsystem): - int index = (nextsystem?tabwidget->indexOf(sys2tabpage[nextsystem]):99999); - tabwidget->insertTab(index,sys2tabpage[sys],sys->name()); - int index2 = tabwidget->indexOf(sys2tabpage[sys]); - if (index2!=-1) { - tabwidget->setTabEnabled(index2,true); - } - } - } - } else { - //Fixme: if system being turned off has selections, we should deselect!! - channel->turnOff(sys,false); - foreach(VP1GraphicsItemCollection*ic,system2itemcols.value(sys)) { - ic->detachFromView(); - } - if (tabwidget&&sys2tabpage.contains(sys)) { - int index = tabwidget->indexOf(sys2tabpage[sys]); - if (index!=-1) { - tabwidget->setTabEnabled(index,false); - tabwidget->removeTab(index); - } - } - } - - view->scene()->update(); - -} - -//___________________________________________________________________________ -void IVP12DStandardChannelWidget::addSystem(IVP12DSystemSimple* sys, const SystemOptions& options ) -{ - addSystem((IVP12DSystem*)sys,options); -} - -//___________________________________________________________________________ -void IVP12DStandardChannelWidget::setBackgroundColor(const QColor & col) -{ - if (!col.isValid()) - return; - m_d->view->setBackgroundBrush(col); -} - -//___________________________________________________________________________ -void IVP12DStandardChannelWidget::showControlsForSystem( ) -{ - if (!m_d->tabwidget) - return; - IVP1System * sys = static_cast<IVP1System*>(sender()); - if (!sys) { - message("showControlsForSystem Error: Unable to determine system identity."); - return; - } - if (!m_d->sys2tabpage.contains(sys)) { - //Dont send warning here. The system in question might simply not have a controller! - return; - } - - int index = m_d->tabwidget->indexOf(m_d->sys2tabpage[sys]); - if (index<0||!m_d->tabwidget->isTabEnabled(index)) { - message("Warning: Asked to show controller for a disabled system. Surely you jest?"); - return; - } - - m_d->tabwidget->setCurrentIndex(index); -} - - -//___________________________________________________________________________ -QByteArray IVP12DStandardChannelWidget::saveState() -{ - VP1Msg::messageVerbose("IVP12DStandardChannelWidget::saveState"); - // ===> Setup stream writing to a byteArray: - QByteArray byteArray; - QBuffer buffer(&byteArray); - buffer.open(QIODevice::WriteOnly); - QDataStream out(&buffer); - - // ===> Write Data: - - //Version & base state: - out << (qint32)0; //version - out << IVP1ChannelWidget::saveState();//Always include state info from the base class. - - //Background color: - out << m_d->colorselectbutton->color(); - - //Systems turned on/off: - //Fixme: Make sure that if you have two copies of the same system, - //that the text in the checkbox gets appended some stuff like [1], - //[2], etc., so that the strings used here will be unique. - QMap<QString, bool> sysname2turnedon; - QMap<QCheckBox*,IVP1System*>::const_iterator it = m_d->checkbox2system.constBegin(); - while (it != m_d->checkbox2system.constEnd()) { - sysname2turnedon.insert(it.key()->text(),it.key()->isChecked()); - ++it; - } - - out << sysname2turnedon; - - //Current system tab: - if (m_d->tabwidget) - out << m_d->tabwidget->tabText(m_d->tabwidget->currentIndex()); - else - out << QString(""); - - // ===> Finish up: - buffer.close(); - return byteArray; -} - -//___________________________________________________________________________ -void IVP12DStandardChannelWidget::restoreFromState(QByteArray ba) -{ - VP1Msg::messageVerbose("IVP12DStandardChannelWidget::restoreFromState"); - - // ===> Setup stream for getting the contents of the byteArray: - QBuffer buffer(&ba); - buffer.open(QIODevice::ReadOnly); - QDataStream state(&buffer); - // ===> Check version and pass on state info to base class: - qint32 version; - state >> version; - if (version!=0) { - message("Warning: State data in .vp1 file is in wrong format - ignoring!"); - return; - } - QByteArray basestate; - state >> basestate; - IVP1ChannelWidget::restoreFromState(basestate); - // ===> Decode the state info: - - QColor bgdcol; - state >> bgdcol; - if (bgdcol!=m_d->colorselectbutton->color()) - m_d->colorselectbutton->setColor(bgdcol); - setBackgroundColor(bgdcol); - - //Switch systems on/off: - QMap<QString, bool> sysname2turnedon; - state >> sysname2turnedon; - QMap<QCheckBox*,IVP1System*>::const_iterator it = m_d->checkbox2system.constBegin(); - while (it != m_d->checkbox2system.constEnd()) { - if (sysname2turnedon.contains(it.key()->text())) { - if (sysname2turnedon[it.key()->text()]!=it.key()->isChecked()) - it.key()->setChecked(sysname2turnedon[it.key()->text()]); - } else { - message("Warning: Config data does not contain information about switched state of subsystem '"+it.key()->text()+"'"); - } - ++it; - } - - //Current system tab - QString tabname; - state >> tabname; - if (m_d->tabwidget) { - for (int i = 0; i < m_d->tabwidget->count(); ++i) { - if (m_d->tabwidget->tabText(i) == tabname) { - m_d->tabwidget->setCurrentIndex(i); - break; - } - } - } - - // ===> Finish up: - buffer.close(); -} diff --git a/GeoModelVisualization/VP1Base/src/IVP12DSystem.cxx b/GeoModelVisualization/VP1Base/src/IVP12DSystem.cxx deleted file mode 100644 index b7358070117b597c713c390bdc3489d6f0ebdd3a..0000000000000000000000000000000000000000 --- a/GeoModelVisualization/VP1Base/src/IVP12DSystem.cxx +++ /dev/null @@ -1,85 +0,0 @@ -/* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -*/ - -///////////////////////////////////////////////////////////// -// // -// Implementation of class IVP12DSystem // -// // -// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // -// // -// Initial version: April 2007 // -// // -///////////////////////////////////////////////////////////// - -#include "VP1Base/IVP12DSystem.h" -#include "VP1Base/VP1GraphicsItemCollection.h" -#include <cassert> - -//Default implementations that do not do anything: -void IVP12DSystem::itemPicked(VP1GraphicsItemCollection*,QGraphicsItem*) {} -void IVP12DSystem::itemGotEvent(VP1GraphicsItemCollection*,QGraphicsItem*,QEvent*) {} -void IVP12DSystem::selectionChanged(VP1GraphicsItemCollection*,QList<QGraphicsItem*>) {} - -//____________________________________________________________________ -class IVP12DSystem::Imp { -public: - QSet<VP1GraphicsItemCollection*> collections; -}; - - -//____________________________________________________________________ -IVP12DSystem::IVP12DSystem(const QString & name, const QString & information, const QString & contact_info) - : IVP1System(name,information,contact_info), m_d(new Imp) -{ -} - -//____________________________________________________________________ -IVP12DSystem::~IVP12DSystem() -{ - delete m_d; m_d=0; -} - -//____________________________________________________________________ -void IVP12DSystem::registerItemCollection(VP1GraphicsItemCollection*ic) -{ - assert(!m_d->collections.contains(ic) - &&"IVP12DSystem::registerItemCollection Error: Item collection registered twice"); - m_d->collections<<ic; - connect(ic,SIGNAL(itemPicked(QGraphicsItem*)),this,SLOT(itemPickedPrivate(QGraphicsItem*))); - connect(ic,SIGNAL(itemGotEvent(QGraphicsItem*,QEvent*)),this,SLOT(itemGotEventPrivate(QGraphicsItem*,QEvent*))); - connect(ic,SIGNAL(selectionChanged(QList<QGraphicsItem*>)),this,SLOT(selectionChangedPrivate(QList<QGraphicsItem*>))); -} - -//____________________________________________________________________ -QSet<VP1GraphicsItemCollection*> IVP12DSystem::getItemCollections() -{ - return m_d->collections; -} - -//____________________________________________________________________ -void IVP12DSystem::itemPickedPrivate(QGraphicsItem*item) -{ - VP1GraphicsItemCollection * ic = static_cast<VP1GraphicsItemCollection*>(sender()); - assert(ic&&ic->interactionMode()==VP1GraphicsItemCollection::SINGLEPICKS); - itemPicked(ic,item); - itemFromSystemSelected(); -} - -//____________________________________________________________________ -void IVP12DSystem::itemGotEventPrivate(QGraphicsItem*item,QEvent*event) -{ - VP1GraphicsItemCollection * ic = static_cast<VP1GraphicsItemCollection*>(sender()); - assert(ic&&ic->interactionMode()==VP1GraphicsItemCollection::EVENTS); - itemGotEvent(ic,item,event); - itemFromSystemSelected(); -} - -//____________________________________________________________________ -void IVP12DSystem::selectionChangedPrivate(QList<QGraphicsItem*> items) -{ - VP1GraphicsItemCollection * ic = static_cast<VP1GraphicsItemCollection*>(sender()); - assert(ic&&ic->interactionMode()==VP1GraphicsItemCollection::SELECTIONS); - selectionChanged(ic,items); - itemFromSystemSelected(); -} diff --git a/GeoModelVisualization/VP1Base/src/IVP12DSystemSimple.cxx b/GeoModelVisualization/VP1Base/src/IVP12DSystemSimple.cxx deleted file mode 100644 index 3510522b7b1339721a507c41f37f8e83d46c2831..0000000000000000000000000000000000000000 --- a/GeoModelVisualization/VP1Base/src/IVP12DSystemSimple.cxx +++ /dev/null @@ -1,117 +0,0 @@ -/* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -*/ - -///////////////////////////////////////////////////////////// -// // -// Implementation of class IVP12DSystemSimple // -// // -// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // -// // -// Initial version: April 2007 // -// // -///////////////////////////////////////////////////////////// - -#include "VP1Base/IVP12DSystemSimple.h" -#include "VP1Base/VP1GraphicsItemCollection.h" -#include <cassert> - -void IVP12DSystemSimple::systemcreate(StoreGateSvc*) {} -QWidget * IVP12DSystemSimple::buildController() { return 0; } -void IVP12DSystemSimple::buildPermanentItemCollection(StoreGateSvc*,VP1GraphicsItemCollection*){} -void IVP12DSystemSimple::buildEventItemCollection(StoreGateSvc *, VP1GraphicsItemCollection*) {} -void IVP12DSystemSimple::systemuncreate() {} -void IVP12DSystemSimple::systemerase() {} - -//____________________________________________________________________ -class IVP12DSystemSimple::Imp { -public: - VP1GraphicsItemCollection* itemcollectionPermanent; - VP1GraphicsItemCollection* itemcollectionEvent; - bool wasrefreshed; - bool wascreated; -}; - -//____________________________________________________________________ -IVP12DSystemSimple::IVP12DSystemSimple(const QString & name, const QString & information, const QString & contact_info) - : IVP12DSystem(name,information,contact_info), m_d(new Imp) -{ - m_d->itemcollectionPermanent = new VP1GraphicsItemCollection(this); - m_d->itemcollectionEvent = new VP1GraphicsItemCollection(this); - - registerItemCollection(m_d->itemcollectionPermanent); - registerItemCollection(m_d->itemcollectionEvent); - - m_d->wasrefreshed=false; - m_d->wascreated=false; -} - -//____________________________________________________________________ -IVP12DSystemSimple::~IVP12DSystemSimple() -{ - delete m_d; m_d=0; -} - -//____________________________________________________________________ -void IVP12DSystemSimple::create(StoreGateSvc* detstore) -{ - assert(!m_d->wascreated); - systemcreate(detstore); - - QWidget * controller = buildController(); - if (controller) - registerController(controller); - - bool hasview = m_d->itemcollectionPermanent->isAttachedToView(); - if (hasview) - m_d->itemcollectionPermanent->detachFromView(); - buildPermanentItemCollection(detstore,m_d->itemcollectionPermanent); - if (hasview) - m_d->itemcollectionPermanent->reattachToView(); - m_d->wascreated=true; -} - -//____________________________________________________________________ -void IVP12DSystemSimple::refresh(StoreGateSvc* sg) -{ - assert(m_d->wascreated); - assert(!m_d->wasrefreshed); - - bool hasview = m_d->itemcollectionEvent->isAttachedToView(); - if (hasview) - m_d->itemcollectionEvent->detachFromView(); - updateGUI(); - buildEventItemCollection(sg, m_d->itemcollectionEvent); - updateGUI(); - if (hasview) - m_d->itemcollectionEvent->reattachToView(); - updateGUI(); - - m_d->wasrefreshed=true; -} - -//____________________________________________________________________ -void IVP12DSystemSimple::erase() -{ - assert(m_d->wascreated); - assert(m_d->wasrefreshed); - systemerase(); - m_d->itemcollectionEvent->clear(); - m_d->wasrefreshed=false; -} - -//____________________________________________________________________ -void IVP12DSystemSimple::uncreate() -{ - messageDebug("uncreate()..."); - - assert(m_d->wascreated); - assert(!m_d->wasrefreshed); - if (m_d->itemcollectionEvent->isAttachedToView()) - m_d->itemcollectionEvent->detachFromView(); - if (m_d->itemcollectionPermanent->isAttachedToView()) - m_d->itemcollectionPermanent->detachFromView(); - systemuncreate(); - m_d->itemcollectionPermanent->clear(); - m_d->wascreated=false; -} diff --git a/GeoModelVisualization/VP1Base/src/IVP13DChannelWidget.cxx b/GeoModelVisualization/VP1Base/src/IVP13DChannelWidget.cxx index 712bf77bf0dc720556f7f0d856a08d82e01da7f9..21444fddab44cee52f1d85928dca49b8bef1c728 100644 --- a/GeoModelVisualization/VP1Base/src/IVP13DChannelWidget.cxx +++ b/GeoModelVisualization/VP1Base/src/IVP13DChannelWidget.cxx @@ -96,11 +96,10 @@ void IVP13DChannelWidget::setUpdatesEnabled ( bool enable ) //void IVP13DChannelWidget::registerRenderArea(SoQtRenderArea* ra) void IVP13DChannelWidget::registerRenderArea(VP1ExaminerViewer* ra) { - if (!ra) { + if (!ra) { message("Error - tried to register NULL render area!"); return; } - VP1QtInventorUtils::ensureInitLineWidthAndPointSize(ra); m_d->renderareas.push_back(ra); diff --git a/GeoModelVisualization/VP1Base/src/IVP1ChannelWidget.cxx b/GeoModelVisualization/VP1Base/src/IVP1ChannelWidget.cxx index 35639124ceb9898103805b44ddbb0701c3b01823..3ba915a0f225a4ee2c52224bb3fcb80463e3f272 100644 --- a/GeoModelVisualization/VP1Base/src/IVP1ChannelWidget.cxx +++ b/GeoModelVisualization/VP1Base/src/IVP1ChannelWidget.cxx @@ -306,9 +306,10 @@ void IVP1ChannelWidget::setCanRegister(const bool&c,const bool&s) QPixmap IVP1ChannelWidget::getSnapshot(bool transp, int width, bool batch) { VP1Msg::messageVerbose("IVP1ChannelWidget::getSnapshot() - using QPixmap::grabWidget()"); - VP1Msg::messageVerbose("(and so, not using the values - transp: "+QString::number(transp)+" - width: "+QString::number(width)+" - batch: " + batch +")"); + VP1Msg::messageVerbose("(and so, not using the values - transp: "+QString::number(transp)+" - width: "+QString::number(width)+" - batch: " + (char) batch +")"); - return QPixmap::grabWidget( this ); + // return QPixmap::grabWidget( this ); + return grab(); } //_______________________________________________________ diff --git a/GeoModelVisualization/VP1Base/src/IVP1System.cxx b/GeoModelVisualization/VP1Base/src/IVP1System.cxx index b7c6fffe4bb12cf991b399f8adf744b633a20c36..79f59b7cbecdad8b5acf745147fc780f84001fd4 100644 --- a/GeoModelVisualization/VP1Base/src/IVP1System.cxx +++ b/GeoModelVisualization/VP1Base/src/IVP1System.cxx @@ -266,7 +266,7 @@ void IVP1System::updateGUI() { //assert(m_d->allowupdategui); //assert(m_d->state==ERASED); - if ( m_d->allowupdategui && qApp->hasPendingEvents() ) { + if ( m_d->allowupdategui /*&& qApp->hasPendingEvents() deprecated in Qt6*/ ) { qApp->processEvents(); } diff --git a/GeoModelVisualization/VP1Base/src/PhiSectionWidget.cxx b/GeoModelVisualization/VP1Base/src/PhiSectionWidget.cxx index 9fbff1d81051e0ddfb3da4e1a7a455d76bb5d7cb..58483d893fe2857abf0244b5c05ecc365c07085f 100644 --- a/GeoModelVisualization/VP1Base/src/PhiSectionWidget.cxx +++ b/GeoModelVisualization/VP1Base/src/PhiSectionWidget.cxx @@ -834,7 +834,7 @@ void PhiSectionWidget::setAllowedNumberOfSectors(QList<int> allowedNSectors, boo m_d->allowCustomNSectors = allowCustom; - qSort(allowedNSectors); + std::sort(allowedNSectors.begin(), allowedNSectors.end()); if (m_d->allowedNSectors==allowedNSectors) { return; } diff --git a/GeoModelVisualization/VP1Base/src/VP12DExaminerViewer.cxx b/GeoModelVisualization/VP1Base/src/VP12DExaminerViewer.cxx deleted file mode 100644 index c85595cfa5a4517213180054cc91e02f1678bc38..0000000000000000000000000000000000000000 --- a/GeoModelVisualization/VP1Base/src/VP12DExaminerViewer.cxx +++ /dev/null @@ -1,326 +0,0 @@ -/* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -*/ - -///////////////////////////////////////////////////////////// -// // -// Implementation of class VP12DExaminerViewer // -// // -// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // -// // -// Initial version: April 2007 // -// Major update to support multiple views: July 2007 // -// // -///////////////////////////////////////////////////////////// - -#include "VP1Base/VP12DExaminerViewer.h" -#include "VP1Base/VP1GraphicsView.h" -#include "ui_vp12dexaminerviewerform.h" -#include <iostream> - -//Fixme: If you set seekmode in one view, then even after you use it -//up, the other views will still be in seek mode. I guess we need a -//seekmodedone signal and an endSeekMode slot in vp1graphicsview. - -//____________________________________________________________________ -class VP12DExaminerViewer::Imp { -public: - VP12DExaminerViewer * theclass; - Ui::VP12DExaminerViewerForm * ui; - bool singleviewmode; - - //Common init stuff for the constructors: - void init1();//Before the views are setup in the stackwidget - void init2();//After the views are setup in the stackwidget - - //For some pushbuttons, only the visible view should be - //connected. Thus use the following when changing view: - void connectButtonsToView(VP1GraphicsView*); - void disconnectButtonsFromView(VP1GraphicsView*); - - //Extra info for multi-view mode: - QList<QPair<QString,QString> > multiviews_viewidAndIconUrl; - QMap<QString,VP1GraphicsView*> multiviews_viewid2view; - QMap<QPushButton*,QString> button2viewid; - - - //Helpers - void setModeAllViews(VP1GraphicsView::Mode); - - -}; - - -//____________________________________________________________________ -void VP12DExaminerViewer::Imp::init1() -{ - ui = new Ui::VP12DExaminerViewerForm; - ui->setupUi(theclass); - - //Clear stack widget: - - while (ui->stackedWidget_views->count()) - ui->stackedWidget_views->removeWidget(ui->stackedWidget_views->currentWidget()); - - //Setup mode buttons: - connect(ui->pushButton_pick,SIGNAL(clicked()),theclass,SLOT(setPickMode())); - connect(ui->pushButton_changeview,SIGNAL(clicked()),theclass,SLOT(setChangeViewMode())); - connect(ui->pushButton_seek,SIGNAL(clicked()),theclass,SLOT(setSeekMode())); - - //Hide unused buttons: - ui->pushButton_zoomplus->hide(); - ui->pushButton_zoomminus->hide(); -} - -//____________________________________________________________________ -void VP12DExaminerViewer::Imp::init2() -{ - if (theclass->view()) - connectButtonsToView(theclass->view()); - else - std::cout<<"VP12DExaminerViewer::Imp::init2 WARNING: Current View is NULL"<<std::endl; - //Start in pick mode: - theclass->setPickMode(); - -} - - -//____________________________________________________________________ -VP12DExaminerViewer::VP12DExaminerViewer(QWidget * parent, Qt::WindowFlags f) - : QWidget(parent,f), m_d(new Imp) -{ - m_d->theclass=this; - m_d->singleviewmode = true; - - m_d->init1(); - - //Add graphicsview: - m_d->ui->stackedWidget_views->insertWidget(m_d->ui->stackedWidget_views->count(),new VP1GraphicsView); - - //Setup viewchangebuttons: - m_d->ui->widget_viewchangebuttons->hide(); - - m_d->init2(); -} - -//____________________________________________________________________ -VP12DExaminerViewer::VP12DExaminerViewer(const QList<QPair<QString,QString> >& views, - QWidget * parent, Qt::WindowFlags f) - : QWidget(parent,f), m_d(new Imp) -{ - if (!views.count()) - std::cout<<"VP12DExaminerViewer ERROR: Using multimode constructor with empty list of requested views!"<<std::endl; - - - m_d->theclass=this; - m_d->singleviewmode = false; - - m_d->init1(); - - //Setup layout for the buttons used to change the views: - QVBoxLayout *layout = new QVBoxLayout; - layout->setSpacing(0); - layout->setContentsMargins(0, 0, 0, 0); - QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - sizePolicy.setHorizontalStretch(0); - sizePolicy.setVerticalStretch(0); - m_d->ui->widget_viewchangebuttons->setLayout(layout); - - //Add graphicsviews: - m_d->multiviews_viewidAndIconUrl = views; - VP1GraphicsView * firstview(0); - for (int i = 0; i<views.count();++i) { - - VP1GraphicsView * view = new VP1GraphicsView; - if (!firstview) - firstview=view; - - m_d->multiviews_viewid2view.insert(views.at(i).first,view); - - m_d->ui->stackedWidget_views->insertWidget(m_d->ui->stackedWidget_views->count(),view); - //Add button: - QPushButton* button = new QPushButton(m_d->ui->widget_viewchangebuttons); - button->setToolTip(views.at(i).first); - button->setSizePolicy(sizePolicy); - button->setMinimumSize(QSize(30, 30)); - button->setMaximumSize(QSize(30, 30)); - button->setFocusPolicy(Qt::NoFocus); - button->setIcon(QIcon(views.at(i).second)); - button->setIconSize(QSize(30, 30)); - button->setCheckable(false); - layout->addWidget(button); - //connect button here and put it in button -> view_id map: - connect(button,SIGNAL(clicked()),this,SLOT(changeViewButtonClicked())); - m_d->button2viewid.insert(button,views.at(i).first); - } - - QSpacerItem * spacerItem = new QSpacerItem(20, 1, QSizePolicy::Minimum, QSizePolicy::Expanding); - layout->addItem(spacerItem); - - if (firstview) - m_d->ui->stackedWidget_views->setCurrentWidget(firstview); - else - std::cout<<"VP12DExaminerViewer WARNING: View is NULL"<<std::endl; - - m_d->init2(); - -// VP1GraphicsView a(a); -} - -//____________________________________________________________________ -void VP12DExaminerViewer::Imp::connectButtonsToView(VP1GraphicsView* view) -{ - connect(ui->pushButton_sethome,SIGNAL(clicked()),view,SLOT(setHome())); - connect(ui->pushButton_home,SIGNAL(clicked()),view,SLOT(viewHome())); - connect(ui->pushButton_viewall,SIGNAL(clicked()),view,SLOT(fitViewToContents())); - connect(ui->pushButton_print,SIGNAL(clicked()),view,SLOT(print())); -} - -//____________________________________________________________________ -void VP12DExaminerViewer::Imp::disconnectButtonsFromView(VP1GraphicsView*view) -{ - disconnect(ui->pushButton_sethome,SIGNAL(clicked()),view,SLOT(setHome())); - disconnect(ui->pushButton_home,SIGNAL(clicked()),view,SLOT(viewHome())); - disconnect(ui->pushButton_viewall,SIGNAL(clicked()),view,SLOT(fitViewToContents())); - disconnect(ui->pushButton_print,SIGNAL(clicked()),view,SLOT(print())); -} - -//____________________________________________________________________ -VP12DExaminerViewer::~VP12DExaminerViewer() -{ - delete m_d; m_d=0; -} - -//____________________________________________________________________ -VP1GraphicsView * VP12DExaminerViewer::view() const { - return static_cast<VP1GraphicsView *>(m_d->ui->stackedWidget_views->currentWidget()); - // return m_d->view; -} - -//____________________________________________________________________ -VP1GraphicsView * VP12DExaminerViewer::view(const QString& view_id) const -{ - if (m_d->singleviewmode||!m_d->multiviews_viewid2view.contains(view_id)) - return 0; - - return m_d->multiviews_viewid2view[view_id]; -} - -//____________________________________________________________________ -void VP12DExaminerViewer::Imp::setModeAllViews(VP1GraphicsView::Mode m) -{ - //Change viewmode for all the views: - if (singleviewmode) { - theclass->view()->setMode(m); - } else { - QMap<QString,VP1GraphicsView*>::iterator it, itE = multiviews_viewid2view.end(); - for(it = multiviews_viewid2view.begin(); it!=itE; ++it) { - it.value()->setMode(m); - } - } -} - -//____________________________________________________________________ -void VP12DExaminerViewer::setPickMode() -{ - m_d->ui->pushButton_pick->setChecked(true); - m_d->ui->pushButton_changeview->setChecked(false); - m_d->setModeAllViews(VP1GraphicsView::PICK); -} - -//____________________________________________________________________ -void VP12DExaminerViewer::setChangeViewMode() -{ - m_d->ui->pushButton_pick->setChecked(false); - m_d->ui->pushButton_changeview->setChecked(true); - m_d->setModeAllViews(VP1GraphicsView::CHANGEVIEW); -} - -//____________________________________________________________________ -void VP12DExaminerViewer::setSeekMode() -{ - m_d->setModeAllViews(VP1GraphicsView::SEEK); -} - -//____________________________________________________________________ -QStringList VP12DExaminerViewer::viewIDs() const -{ - if (m_d->singleviewmode) - return QStringList(); - - QStringList l; - QMap<QString,VP1GraphicsView*>::iterator it, itE = m_d->multiviews_viewid2view.end(); - for(it = m_d->multiviews_viewid2view.begin(); it!=itE; ++it) { - l << it.key(); - } - - return l; -} - -//____________________________________________________________________ -QList<QPair<QString,QString> > VP12DExaminerViewer::viewIDsAndIconUrls() const -{ - if (m_d->singleviewmode) - return QList<QPair<QString,QString> >(); - - return m_d->multiviews_viewidAndIconUrl; -} - -//____________________________________________________________________ -bool VP12DExaminerViewer::isSingleViewMode() const -{ - return m_d->singleviewmode; -} - -//____________________________________________________________________ -QString VP12DExaminerViewer::currentView() const -{ - if (m_d->singleviewmode) - return ""; - - VP1GraphicsView* currentview = view(); - if (!currentview) - return ""; - - QMap<QString,VP1GraphicsView*>::iterator it, itE = m_d->multiviews_viewid2view.end(); - for(it = m_d->multiviews_viewid2view.begin(); it!=itE; ++it) { - if (it.value()==currentview) - return it.key(); - } - - return ""; -} - -//____________________________________________________________________ -void VP12DExaminerViewer::setShownView(QString viewid) -{ - if (m_d->singleviewmode) - return; - - if (!m_d->multiviews_viewid2view.contains(viewid)) - return; - - VP1GraphicsView* oldview = view(); - VP1GraphicsView* newview = m_d->multiviews_viewid2view[viewid]; - if (!oldview||!newview) - return; - if (oldview==newview) - return; - - currentViewAboutToChange(newview); - - m_d->disconnectButtonsFromView(oldview); - m_d->ui->stackedWidget_views->setCurrentWidget(newview); - m_d->connectButtonsToView(newview); - - currentViewChanged(); -} - -//____________________________________________________________________ -void VP12DExaminerViewer::changeViewButtonClicked() -{ - QPushButton * button = static_cast<QPushButton*>(sender()); - if (!button||!m_d->button2viewid.contains(button)) - return; - setShownView(m_d->button2viewid[button]); -} diff --git a/GeoModelVisualization/VP1Base/src/VP1CollectionWidget.cxx b/GeoModelVisualization/VP1Base/src/VP1CollectionWidget.cxx index 65f36028b536a466a84ad4dcdf958a8e1dd9b856..4ca0117158cf6aa6c70b404232d0dc8c15956034 100644 --- a/GeoModelVisualization/VP1Base/src/VP1CollectionWidget.cxx +++ b/GeoModelVisualization/VP1Base/src/VP1CollectionWidget.cxx @@ -110,7 +110,7 @@ void VP1CollectionWidget::Imp::repopulateGUIFromCollections() QVBoxLayout * vlayout = new QVBoxLayout; vlayout->setSpacing(0); - vlayout->setMargin(0); + // vlayout->setMargin(0); if (collections.isEmpty()) { QHBoxLayout * labellayout = new QHBoxLayout; labellayout->setSpacing(0); @@ -122,8 +122,8 @@ void VP1CollectionWidget::Imp::repopulateGUIFromCollections() QSet<QString> sections; foreach (VP1Collection* col,collections) sections.insert(col->section()); - QList<QString> sectionsSorted = sections.toList(); - qSort(sectionsSorted); + QList<QString> sectionsSorted(sections.begin(),sections.end());// = sections.toList(); + std::sort(sectionsSorted.begin(), sectionsSorted.end()); theclass->sortSections(sectionsSorted); const bool nosectionlabels = sectionsSorted.count() == 1 && sectionsSorted.at(0).isEmpty(); @@ -149,7 +149,7 @@ void VP1CollectionWidget::Imp::repopulateGUIFromCollections() QGridLayout * gridLayout = new QGridLayout; gridLayout->setHorizontalSpacing(6); gridLayout->setVerticalSpacing(0); - gridLayout->setMargin(0); + //gridLayout->setMargin(0); if (!nosectionlabels) gridLayout->addItem(new QSpacerItem(10, 1, QSizePolicy::Fixed, QSizePolicy::Fixed),0,0); vlayout->addLayout(gridLayout); @@ -207,7 +207,7 @@ void VP1CollectionWidget::Imp::repopulateGUIFromCollections() vlayout->addStretch(1); QHBoxLayout * hlayout = new QHBoxLayout; - hlayout->setMargin(0); + //hlayout->setMargin(0); hlayout->setSpacing(0); hlayout->addLayout(vlayout); hlayout->addStretch(1); @@ -316,8 +316,8 @@ QList<qint32> VP1CollectionWidget::Imp::visibleStdCollectionTypesFromVisStdCols( QSet<qint32> vt; foreach(VP1StdCollection* stdcol,l) vt.insert(stdcol->collTypeID()); - QList<qint32> vistypes = vt.toList(); - qSort(vistypes); + QList<qint32> vistypes(vt.begin(),vt.end());// = vt.toList(); + std::sort(vistypes.begin(),vistypes.end()); return vistypes; } diff --git a/GeoModelVisualization/VP1Base/src/VP1Controller.cxx b/GeoModelVisualization/VP1Base/src/VP1Controller.cxx index 0c8a219d51c4da7c63e8b162d9aab45e1080429f..e3f9deef6cdca241999f05c97a2a7d37b90e30fd 100644 --- a/GeoModelVisualization/VP1Base/src/VP1Controller.cxx +++ b/GeoModelVisualization/VP1Base/src/VP1Controller.cxx @@ -290,7 +290,7 @@ QButtonGroup * VP1Controller::defineRadioButtonGroup( QRadioButton * rb0, QRadio { QList<QRadioButton *> l; l << rb0 << rb1 << rb2 << rb3 << rb4 << rb5 << rb6 << rb7 << rb8 << rb9; - l.removeAll(0); + l.removeAll(nullptr); return defineRadioButtonGroup(l); } diff --git a/GeoModelVisualization/VP1Base/src/VP1ControllerHelper.cxx b/GeoModelVisualization/VP1Base/src/VP1ControllerHelper.cxx index 52379f79978780c27634ed5a2dece0e16fdb4696..46e44e9e721fbbcb5f89af4a6195ffcbd7adf0ab 100644 --- a/GeoModelVisualization/VP1Base/src/VP1ControllerHelper.cxx +++ b/GeoModelVisualization/VP1Base/src/VP1ControllerHelper.cxx @@ -49,10 +49,10 @@ QWidget * VP1ControllerHelper::compositionController( const QList<IVP1System*>& QWidget * tab_general = new QWidget(0); QVBoxLayout * vboxLayout1 = new QVBoxLayout(tab_general); vboxLayout1->setSpacing(6); - vboxLayout1->setMargin(9); + // vboxLayout1->setMargin(9); QHBoxLayout * hboxLayout = new QHBoxLayout(); hboxLayout->setSpacing(6); - hboxLayout->setMargin(0); + //hboxLayout->setMargin(0); QLabel * tab_general_label = new QLabel(tab_general); tab_general_label->setText("No systems can be switched on/off in this channel."); hboxLayout->addWidget(tab_general_label); @@ -61,12 +61,12 @@ QWidget * VP1ControllerHelper::compositionController( const QList<IVP1System*>& vboxLayout1->addLayout(hboxLayout); QHBoxLayout * hboxLayout1 = new QHBoxLayout(); hboxLayout1->setSpacing(0); - hboxLayout1->setMargin(0); + //hboxLayout1->setMargin(0); QSpacerItem * spacerItem1 = new QSpacerItem(25, 2, QSizePolicy::Fixed, QSizePolicy::Fixed); hboxLayout1->addItem(spacerItem1); QVBoxLayout *vboxLayout_checkboxes = new QVBoxLayout(); vboxLayout_checkboxes->setSpacing(6); - vboxLayout_checkboxes->setMargin(0); + //vboxLayout_checkboxes->setMargin(0); hboxLayout1->addLayout(vboxLayout_checkboxes); QSpacerItem * spacerItem2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); hboxLayout1->addItem(spacerItem2); @@ -94,7 +94,7 @@ QWidget * VP1ControllerHelper::compositionController( const QList<IVP1System*>& colorselectbutton = new VP1ColorSelectButton(tab_general,Qt::black); QHBoxLayout * hboxLayout2 = new QHBoxLayout(); hboxLayout2->setSpacing(6); - hboxLayout2->setMargin(0); + //hboxLayout2->setMargin(0); hboxLayout2->addWidget(colorselectbutton); hboxLayout2->addWidget(new QLabel("Set background")); QSpacerItem * spacerItem4 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); @@ -109,7 +109,7 @@ QWidget * VP1ControllerHelper::compositionController( const QList<IVP1System*>& extrawidget->setParent(tab_general); QHBoxLayout * hboxLayout_extra = new QHBoxLayout(); hboxLayout_extra->setSpacing(6); - hboxLayout_extra->setMargin(0); + //hboxLayout_extra->setMargin(0); hboxLayout_extra->addWidget(extrawidget); QSpacerItem * spacerItem_extra1 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); hboxLayout_extra->addItem(spacerItem_extra1); diff --git a/GeoModelVisualization/VP1Base/src/VP1CustomTourEditor.cxx b/GeoModelVisualization/VP1Base/src/VP1CustomTourEditor.cxx index 8bbc68ca0a75800a10f22e758c23f1d97ae36044..e7fb913d63872a50bc02eda797ab626bdea3ca4b 100644 --- a/GeoModelVisualization/VP1Base/src/VP1CustomTourEditor.cxx +++ b/GeoModelVisualization/VP1Base/src/VP1CustomTourEditor.cxx @@ -192,7 +192,7 @@ void VP1CustomTourEditor::frameStepToEarlier() int iframe(m_d->frames.indexOf(dynamic_cast<VP1CustomTourFrameWidget*>(sender()))); if (iframe<=0) return;//not found or already at start - m_d->frames.swap(iframe-1,iframe); + m_d->frames.swapItemsAt(iframe-1,iframe); m_d->updateFrameListVisuals(); } @@ -204,7 +204,7 @@ void VP1CustomTourEditor::frameStepToLater() return; if (iframe>=m_d->frames.count()-1) return;//already at end - m_d->frames.swap(iframe,iframe+1); + m_d->frames.swapItemsAt(iframe,iframe+1); m_d->updateFrameListVisuals(); } @@ -279,7 +279,7 @@ void VP1CustomTourEditor::swap( VP1CustomTourFrameWidget * frame1, ||iframe1>=m_d->frames.count() ||iframe2>=m_d->frames.count() ) return; - m_d->frames.swap(iframe1,iframe2); + m_d->frames.swapItemsAt(iframe1,iframe2); m_d->updateFrameListVisuals(); } diff --git a/GeoModelVisualization/VP1Base/src/VP1CustomTourFrameWidget.cxx b/GeoModelVisualization/VP1Base/src/VP1CustomTourFrameWidget.cxx index 506f7693f8c6b4adc980b590cbb42a8cb6a71d12..ef07468298aa60c84bccc5b97031cd8eceae7afa 100644 --- a/GeoModelVisualization/VP1Base/src/VP1CustomTourFrameWidget.cxx +++ b/GeoModelVisualization/VP1Base/src/VP1CustomTourFrameWidget.cxx @@ -116,7 +116,7 @@ QByteArray VP1CustomTourFrameWidget::serialise() const s.save(m_d->ui.doubleSpinBox_clipVolumePercentOfATLAS); s.save(m_d->ui.comboBox_approachMethod); s.save(m_d->ui.checkBox_frameEnabled); - s.save(m_d->ui.label_snapshot->pixmap() ? *(m_d->ui.label_snapshot->pixmap()) : QPixmap()); + s.save(m_d->ui.label_snapshot->pixmap()); s.warnUnsaved(this); return s.result(); } @@ -220,10 +220,15 @@ void VP1CustomTourFrameWidget::mouseMoveEvent(QMouseEvent *event) QMimeData *mimeData = new QMimeData; mimeData->setData("vp1/customtourframe", QByteArray() ); drag->setMimeData(mimeData);//drag assumes ownership of mimeData + +#if QT_VERSION >= 0x060000 + QPixmap pm =m_d->ui.label_snapshot->pixmap(); +#else QPixmap pm = m_d->ui.label_snapshot->pixmap() ? *(m_d->ui.label_snapshot->pixmap()) : QPixmap(); - if (!pm.isNull()) - drag->setPixmap(pm ); +#endif + if (!pm.isNull()) drag->setPixmap(pm ); drag->exec(Qt::CopyAction | Qt::MoveAction); + } //____________________________________________________________________ diff --git a/GeoModelVisualization/VP1Base/src/VP1ExaminerViewer.cxx b/GeoModelVisualization/VP1Base/src/VP1ExaminerViewer.cxx index 9f300c4d26ba572e52ae367462706e5f3ac864bd..f5fee1fbdaf804545816d5888e0144aeee01cfd9 100644 --- a/GeoModelVisualization/VP1Base/src/VP1ExaminerViewer.cxx +++ b/GeoModelVisualization/VP1Base/src/VP1ExaminerViewer.cxx @@ -52,7 +52,8 @@ #include <QFileDialog> #include <QInputDialog> #include <QPushButton> -#include <QGLFormat> +#include <QActionGroup> +//#include <QGLFormat> #include <map> #include <iostream> @@ -563,7 +564,7 @@ VP1ExaminerViewer::VP1ExaminerViewer(QWidget * parent, } // test Ric - VP1Msg::messageVerbose("is stereo: " + QString(isStereoViewing()) + " - offset: " + QString::number(getStereoOffsetSlot()) + " - type: " + QString::number(getStereoType()) ); + VP1Msg::messageVerbose("is stereo: " + QString((char) isStereoViewing()) + " - offset: " + QString::number(getStereoOffsetSlot()) + " - type: " + QString::number(getStereoType()) ); } @@ -1282,7 +1283,7 @@ void VP1ExaminerViewer::Imp::detectorZoomButtonClicked(std::pair<REGION,VIEW> p) { grabFocus(); - VP1Msg::messageVerbose("detectorZoomButtonClicked region = " + toString(p.first) + ", from " + QString(p.second) + " Z axis" ); + VP1Msg::messageVerbose("detectorZoomButtonClicked region = " + toString(p.first) + ", from " + QString((char) p.second) + " Z axis" ); SoNode * rootnode = theclass->getSceneGraph(); if (!rootnode) { diff --git a/GeoModelVisualization/VP1Base/src/VP1GraphicsItemCollection.cxx b/GeoModelVisualization/VP1Base/src/VP1GraphicsItemCollection.cxx deleted file mode 100644 index 6e0cb417f92c3530661dfaf3fc247f7a7542b08e..0000000000000000000000000000000000000000 --- a/GeoModelVisualization/VP1Base/src/VP1GraphicsItemCollection.cxx +++ /dev/null @@ -1,359 +0,0 @@ -/* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -*/ - -///////////////////////////////////////////////////////////// -// // -// Implementation of class VP1GraphicsItemCollection // -// // -// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // -// // -// Initial version: April 2007 // -// // -///////////////////////////////////////////////////////////// - -#include "VP1Base/VP1GraphicsItemCollection.h" -#include "VP1Base/VP1GraphicsView.h" - -#include <QGraphicsItem> -#include <QGraphicsScene> -#include <QHash> -#include <QSet> - -#include <iostream> -#include <cassert> - -//____________________________________________________________________ -class VP1GraphicsItemCollection::Imp { -public: - - QGraphicsScene *scene; - VP1GraphicsView *lastview; - VP1GraphicsView *view; - bool ignoreall_int; - bool ignoreall_move; - int nactiveitems; - - void setEnabledMovableItems(const bool& enabled); - bool ignoresInteractions() const; - - - QHash<QGraphicsItem*,bool> items2active; - typedef QHash<QGraphicsItem*,bool>::iterator ItemDataMapItr;//fixme: optimise flag. - - //For performance reasons, we keep a separate list of the items that - //are movable (anyone making a collection with 100000 movable items - //will be the first against the wall when the revolution comes): - QSet<QGraphicsItem*> movableitems; - - VP1GraphicsItemCollection::INTERACTIONMODE interactionmode; - -}; - - -//____________________________________________________________________ -VP1GraphicsItemCollection::VP1GraphicsItemCollection( QObject * parent) - : QObject(parent), m_d(new Imp) -{ - m_d->view=0; - m_d->lastview=0; - m_d->scene=0; - m_d->ignoreall_int=false; - m_d->ignoreall_move=false; - m_d->interactionmode=INERT; - m_d->nactiveitems=0; -} - -//____________________________________________________________________ -VP1GraphicsItemCollection::~VP1GraphicsItemCollection() -{ - if (m_d->view) - detachFromView(); - clear(); - delete m_d; -} - -//____________________________________________________________________ -void VP1GraphicsItemCollection::setInteractionMode( const VP1GraphicsItemCollection::INTERACTIONMODE& im ) -{ - assert(!m_d->scene&&"VP1GraphicsItemCollection::setInteractionMode can not be called while a scene is attached."); - if (m_d->scene) { - std::cout<<"VP1GraphicsItemCollection::setInteractionMode can not be called while a scene is attached."<<std::endl; - return; - } - m_d->interactionmode = im; -} - -//____________________________________________________________________ -VP1GraphicsItemCollection::INTERACTIONMODE VP1GraphicsItemCollection::interactionMode() const -{ - return m_d->interactionmode; -} - -//____________________________________________________________________ -void VP1GraphicsItemCollection::addItem(QGraphicsItem*item, const bool& active,const bool&movable) -{ - assert(!m_d->items2active.contains(item)&&"Please do not add the same item twice"); - assert(!item->flags()&&"Please do not add any flags to your items!!"); - - if (m_d->scene) { - //The following must postponed if there is no scene: - m_d->scene->addItem(item); - item->setFlag(QGraphicsItem::ItemIsMovable,(movable&&(!m_d->ignoreall_move))); - } - assert(!m_d->items2active.contains(item)); - m_d->items2active.insert(item,active); - if (active) - ++m_d->nactiveitems; - if (movable) - m_d->movableitems<<item; -} - -//Fixme: Make VP1GraphicsView setScene() private so it is the same throughout a GV lifetime. - -//____________________________________________________________________ -bool VP1GraphicsItemCollection::removeItem(QGraphicsItem*item) -{ - Imp::ItemDataMapItr it = m_d->items2active.find( item ); - if (it==m_d->items2active.end()) - return false; - if (it.value()) - --m_d->nactiveitems; - if (m_d->scene) { - m_d->scene->removeItem(item); - } - m_d->items2active.erase(it); - assert(!m_d->items2active.contains(item)); - - if (!m_d->movableitems.empty()) { - QSet<QGraphicsItem*>::iterator it2 = m_d->movableitems.find(item); - if (it2!=m_d->movableitems.end()) { - assert(m_d->movableitems.contains(item)); - m_d->movableitems.erase(it2); - } - } - assert(!m_d->movableitems.contains(item)); - return true; -} - -//____________________________________________________________________ -bool VP1GraphicsItemCollection::setMovable(QGraphicsItem* item, const bool& movable) -{ - Imp::ItemDataMapItr it = m_d->items2active.find( item ); - if (it==m_d->items2active.end()) - return false; - if (movable==m_d->movableitems.contains(item))//Nothing needs to be done: - return true; - if (movable) { - assert(!m_d->movableitems.contains(item)); - m_d->movableitems<<item; - } else { - assert(m_d->movableitems.contains(item)); - m_d->movableitems.remove(item); - assert(!m_d->movableitems.contains(item)); - } - if (!m_d->ignoreall_move) - item->setFlag(QGraphicsItem::ItemIsMovable,movable); - return true; -} - -//____________________________________________________________________ -bool VP1GraphicsItemCollection::setActive(QGraphicsItem* item, const bool& active) -{ - Imp::ItemDataMapItr it = m_d->items2active.find( item ); - if (it==m_d->items2active.end()) - return false; - it.value()=active; - if (active) - ++m_d->nactiveitems; - else - --m_d->nactiveitems; - return true; -} - -//____________________________________________________________________ -void VP1GraphicsItemCollection::clear(const bool& deleteitems) -{ - //Clear selections before deleting items in order to only get one selectionchanged signal. - if (m_d->view) - m_d->view->clearSelections(); - - Imp::ItemDataMapItr it,itE=m_d->items2active.end(); - if (m_d->scene) { - //Remove item from scene and possible also remove event filter. - for (it=m_d->items2active.begin();it!=itE;++it) - m_d->scene->removeItem(it.key()); - } - if (deleteitems) { - //Delete the items: - for (it=m_d->items2active.begin();it!=itE;++it) { - delete it.key(); - } - } - m_d->items2active.clear(); - m_d->movableitems.clear(); - m_d->nactiveitems=0; -} - -//____________________________________________________________________ -bool VP1GraphicsItemCollection::hasItem(QGraphicsItem* item) const -{ - return m_d->items2active.contains(item); -} - -//____________________________________________________________________ -void VP1GraphicsItemCollection::Imp::setEnabledMovableItems(const bool& enabled) { - if (movableitems.empty()) - return; - QSet<QGraphicsItem*>::iterator it,itE=movableitems.end(); - for (it=movableitems.begin();it!=itE;++it) { - (*it)->setFlag(QGraphicsItem::ItemIsMovable,enabled); - } - -} - -//____________________________________________________________________ -void VP1GraphicsItemCollection::setTemporaryIgnoreInteractions( const bool& b ) -{ - if (m_d->ignoreall_int==b) - return; - m_d->ignoreall_int=b; -} - -//____________________________________________________________________ -void VP1GraphicsItemCollection::setTemporaryIgnoreMovable( const bool& b ) -{ - if (m_d->ignoreall_move==b) - return; - m_d->ignoreall_move=b; - if (m_d->scene) - m_d->setEnabledMovableItems(!b); -} - -//____________________________________________________________________ -bool VP1GraphicsItemCollection::Imp::ignoresInteractions() const -{ - return ( interactionmode==INERT || ignoreall_int ); -} - -//____________________________________________________________________ -void VP1GraphicsItemCollection::attachToView(VP1GraphicsView*view) -{ - assert(!m_d->scene); - assert(!m_d->view); - m_d->scene=view->scene(); - // m_d->lastscene=m_d->scene; - m_d->view=view; - m_d->lastview=m_d->view; - Imp::ItemDataMapItr it,itE=m_d->items2active.end(); - for (it=m_d->items2active.begin();it!=itE;++it) { - m_d->scene->addItem(it.key()); - } - //Update this, since we didnt do any updates while there was no scene: - m_d->setEnabledMovableItems(!m_d->ignoreall_move); -} - -//____________________________________________________________________ -void VP1GraphicsItemCollection::detachFromView() -{ - if (!m_d->view) - return; - m_d->view->removeItemCollection(this); - //NB. The call to removeItemCollection ends up by calling - //VP1GraphicsItemCollection::real_detachFromView(). -} - -//____________________________________________________________________ -void VP1GraphicsItemCollection::real_detachFromView() -{ - //This method is called after the collection has been removed from the the view. - if (!m_d->view) - return; - //Remove item from scene: - Imp::ItemDataMapItr it,itE=m_d->items2active.end(); - for (it=m_d->items2active.begin();it!=itE;++it) { - m_d->scene->removeItem(it.key()); - } - m_d->view=0; - m_d->scene=0; -} - -//____________________________________________________________________ -void VP1GraphicsItemCollection::reattachToView() -{ - if (m_d->view) - return; - assert(m_d->lastview); - m_d->lastview->addItemCollection(this); - //NB. The call to addItemCollection ends up by calling - //VP1GraphicsItemCollection::attachToView(). -} - -//____________________________________________________________________ -bool VP1GraphicsItemCollection::isAttachedToView() -{ - return m_d->view; -} - - -//____________________________________________________________________ -int VP1GraphicsItemCollection::nItems() const -{ - return m_d->items2active.count(); -} - -//____________________________________________________________________ -int VP1GraphicsItemCollection::nActiveItems() const -{ - return m_d->nactiveitems; -} - -//____________________________________________________________________ -int VP1GraphicsItemCollection::nMovableItems() const -{ - return m_d->movableitems.count(); -} - -//____________________________________________________________________ -int VP1GraphicsItemCollection::nPresentlyActiveItems() const -{ - return m_d->ignoresInteractions() ? 0 : m_d->nactiveitems; -} - -//____________________________________________________________________ -int VP1GraphicsItemCollection::nPresentlyMovableItems() const -{ - return m_d->ignoresInteractions() ? 0 : m_d->movableitems.count(); -} - -//____________________________________________________________________ -bool VP1GraphicsItemCollection::itemBelongsAndIsPresentlyActive(QGraphicsItem*item) const -{ - if (!nPresentlyActiveItems()) - return false; - QHash<QGraphicsItem*,bool>::const_iterator it = m_d->items2active.find(item); - - - if (it==m_d->items2active.constEnd()) - return false; - else - return it.value(); -} - -//____________________________________________________________________ -void VP1GraphicsItemCollection::itemPickedPrivate(QGraphicsItem* item) const -{ - itemPicked(item); -} - -//____________________________________________________________________ -void VP1GraphicsItemCollection::itemGotEventPrivate(QGraphicsItem*item,QEvent*event) const -{ - itemGotEvent(item,event); -} - -//____________________________________________________________________ -void VP1GraphicsItemCollection::selectionChangedPrivate(QList<QGraphicsItem*> items) const -{ - selectionChanged(items); -} diff --git a/GeoModelVisualization/VP1Base/src/VP1GraphicsView.cxx b/GeoModelVisualization/VP1Base/src/VP1GraphicsView.cxx deleted file mode 100644 index 81f126709211191abf79585576d0953e3064312b..0000000000000000000000000000000000000000 --- a/GeoModelVisualization/VP1Base/src/VP1GraphicsView.cxx +++ /dev/null @@ -1,1116 +0,0 @@ -/* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -*/ - -///////////////////////////////////////////////////////////// -// // -// Implementation of class VP1GraphicsView // -// // -// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // -// // -// Initial version: April 2007 // -// // -///////////////////////////////////////////////////////////// - -//Todo: Mouse zoom mode (updown...). -// left+middle:zoom. left+middle+right: keep. -// left+right:drag keep mode until click. -// Zoom by rubberband mode. -// Add zoom in/out slots to be like Key_Plus/Key_Minus? -// A changeview drag does not abort a zoom! -// Adjust zoom nsteps based on number of items in view. - - -#include "VP1Base/VP1GraphicsView.h" -#include "VP1Base/VP1GraphicsItemCollection.h" - -#include "VP1Base/IVP12DViewTransformation.h" -#include "VP1Base/VP12DViewRZFishEyeTransformation.h"//fixme -#include "VP1Base/VP12DViewRPhiFishEyeTransformation.h"//fixme - -#include "VP1Base/VP1Settings.h" -#include "VP1Base/VP1Msg.h" - -// QtCore -#include <QTimer> -#include <QQueue> -#include <QSet> -#include <QDir> - -// QtGui -#include <QWheelEvent> -#include <QMouseEvent> -#include <QGraphicsScene> -#include <QScrollBar> -#include <QGraphicsPathItem> -#include <QPrinter> -#include <QPrintDialog> -#include <QPixmap> -#include <QFileDialog> -#include <QTextDocument> -#include <QAbstractTextDocumentLayout> - -// Qt OpenGL -#include <QGLWidget> -#include <QGLFormat> - -#include<iostream>//fixme -#include <cassert> - -//____________________________________________________________________ -class VP1GraphicsView::Imp { -public: - - void init(VP1GraphicsView*); - QGraphicsScene * scene; - VP1GraphicsView * view; - - Mode mode; - Mode lastmajormode;//To go back to the previous major mode when exiting a seek. - - QList<VP1GraphicsItemCollection*> cols_act;//All item collections not inherently INERT - QList<VP1GraphicsItemCollection*> cols_all;//Needed since event inactive collections might have movable items. - - //The following two lists may contain pointers to ic's not presently - //attached to the view since we need to remember settings: - QSet<VP1GraphicsItemCollection*> cols_override_inactive; - QSet<VP1GraphicsItemCollection*> cols_override_unmovable; - - QRectF home; - - QTimer * zoomanim_timer; - int zoomanim_nsteps; - double zoomanim_totaltime; - double zoomfactoronseek; - QQueue<QRectF> zoomanim_queue; - QPainter::RenderHints savedrenderhints; - - QPoint dragzoom_startpoint; - - void setNewSelected(QGraphicsItem*,const bool& multimode=false); - QMap<QGraphicsItem*,HighLightItem*> selecteditems; - -// QList<QGraphicsItem*> selecteditems;//Fixme more than one item!! -// QList<QGraphicsPathItem*> selectionoutlines; - VP1GraphicsItemCollection * ic_multiselection;//Holds the ic when a multiselection is taking place. - void locateActiveItemAtPoint(QGraphicsItem*&,VP1GraphicsItemCollection*& ic, - const QPoint& pos, - VP1GraphicsItemCollection * searchic=0); - void select(QGraphicsItem*item); - void deselect(QGraphicsItem*item); - void HighLightItemBeingDeleted(HighLightItem*); - bool clearselectionsemitsignals; - QList<QGraphicsItem*> lastemittedselecteditems; - - - QString currentsaveimagefile; - void paintDescription(QPainter *painter); - QTextDocument helptext; - QImage *helptextimage; - void createNewHelptextImage(const QRect& imrect); - bool showhelptext; - - //transformation: - IVP12DViewTransformation * transform; - bool transformactive; -}; - -//We make a slightly modified pathitem for highlight item - because we -//need to know when it is killed (which it will be when the user -//removes an item): -//____________________________________________________________________ -class VP1GraphicsView::HighLightItem : public QGraphicsPathItem { -public: - HighLightItem ( const QPainterPath & path, QGraphicsItem * parent, VP1GraphicsView*v) - : QGraphicsPathItem(path,parent),view(v),sendsignalondelete(true) {} - virtual ~HighLightItem() { - std::cout<<"dying"<<std::endl; - if (sendsignalondelete) - view->m_d->HighLightItemBeingDeleted(this); - } - VP1GraphicsView* view; - bool sendsignalondelete; -}; - -//____________________________________________________________________ -VP1GraphicsView::VP1GraphicsView ( QWidget * parent ) - :QGraphicsView(parent), m_d(new Imp) -{ - m_d->init(this); -} - -//____________________________________________________________________ -VP1GraphicsView::VP1GraphicsView ( QGraphicsScene * scene, QWidget * parent ) - : QGraphicsView(scene,parent), m_d(new Imp) -{ - m_d->init(this); -} - -//____________________________________________________________________ -void VP1GraphicsView::Imp::init(VP1GraphicsView*v) -{ - view=v; - view->setTransformationAnchor(AnchorUnderMouse); - view->setResizeAnchor(AnchorViewCenter); - if (QGLFormat::hasOpenGL())//It turns out that when doing x-forward (at least from lxplus) GLX, and thus OpenGL support is not present. - view->setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers),view)); - view->setRenderHint(QPainter::Antialiasing);//QPainter::SmoothPixmapTransform - view->setBackgroundBrush(Qt::black); - if (!view->scene()) - view->setScene(new QGraphicsScene()); - scene=view->scene(); - lastmajormode = mode = PICK; - view->setMode(PICK); - - view->setFrameStyle(QFrame::NoFrame); - - zoomanim_timer = new QTimer(); - QObject::connect(zoomanim_timer, SIGNAL(timeout()), view, SLOT(updateZoomAnimation())); - zoomfactoronseek = 10.0; - //Like this to set the correct timer interval: - zoomanim_nsteps = 24; - view->setAnimatedZoomTime(1500.0);//ms - - // Due to a bug in Qt 4.3.0 (not present in 4.2.3 and supposedly - // fixed in 4.3.1), we have to show the scrollbars if we want to - // have proper scrollhanddrag and seek modes. Therefore we uncomment - // the next two lines - and we should reenable them for Qt4.3.1 (fixme). - // view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - // view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - - //Make sure that animation aborts if user moves a scrollbar (in case someone turns them on): - QObject::connect(view->horizontalScrollBar(),SIGNAL(sliderMoved(int)),view,SLOT(abortZoomAnimation())); - QObject::connect(view->verticalScrollBar(),SIGNAL(sliderMoved(int)),view,SLOT(abortZoomAnimation())); - clearselectionsemitsignals=true; - ic_multiselection=0; -// selecteditem=0; -// selectionoutline=0; - helptextimage=0; - showhelptext=false; - - transform = 0; - transformactive = false; - //fixme: - if (false) { - transformactive = true; - // transform = new VP12DViewRZFishEyeTransformation(); - transform = new VP12DViewRPhiFishEyeTransformation(); - view->setInteractive ( false ); - } - -} - -//____________________________________________________________________ -VP1GraphicsView::~VP1GraphicsView() -{ - delete m_d->transform; - delete m_d; m_d=0; -} - -//____________________________________________________________________ -void VP1GraphicsView::scaleView(qreal scaleFactor) -{ - abortZoomAnimation(); - qreal factor = matrix().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width(); - if (factor < 1e-5 || factor > 1e5)//Fixme:Set as options! - return; - scale(scaleFactor, scaleFactor); -} - -//____________________________________________________________________ -void VP1GraphicsView::fitViewToContents() -{ - if (m_d->transform&&m_d->transformactive) - fitInView( m_d->transform->transform(scene()->sceneRect()), Qt::KeepAspectRatio ); - else - fitInView( scene()->sceneRect(), Qt::KeepAspectRatio ); -} - -//____________________________________________________________________ -void VP1GraphicsView::wheelEvent(QWheelEvent *event) -{ - if (m_d->showhelptext) { - m_d->showhelptext=false; - viewport()->update(); - }; - double ratefact = 0.8; - if (event->modifiers() & Qt::ControlModifier) - ratefact = 0.1; - if (event->modifiers() & Qt::ShiftModifier) - ratefact = 0.01; - scaleView(pow((double)2, -event->delta() / (240.0/ratefact))); -} - -//____________________________________________________________________ -void VP1GraphicsView::keyPressEvent(QKeyEvent *event) -{ -// VP1Msg::messageDebug("VP1GraphicsView::keyPressEvent"); - -// std::string keyText = (event->text()).toStdString(); -// VP1Msg::messageDebug(keyText.c_str()); - - if (m_d->showhelptext&&!(event->key()==Qt::Key_F1||event->key()==Qt::Key_H)) { - m_d->showhelptext=false; - viewport()->update(); - }; - - switch (event->key()) { - case Qt::Key_Home: - if (event->modifiers() & Qt::ControlModifier) - setHome(); - else - viewHome(); - break; - case Qt::Key_F1: - case Qt::Key_H: - m_d->showhelptext=!m_d->showhelptext; - viewport()->update(); - break; - case Qt::Key_1: - fitViewToContents(); - break; - case Qt::Key_Escape: - if (m_d->mode==SEEK) - setMode(m_d->lastmajormode); - else if (m_d->mode==PICK) - setMode(CHANGEVIEW); - else - setMode(PICK); - break; - case Qt::Key_S: - if (m_d->mode!=SEEK) - setMode(SEEK); - else - setMode(m_d->lastmajormode); - break; - case Qt::Key_Plus: - case Qt::Key_Equal: - scaleView(1.2); - break; - case Qt::Key_Minus: - scaleView(1 / 1.2); - break; - case Qt::Key_P: - if (event->modifiers() & Qt::ControlModifier) - saveImage(); - else - print(); - break; - default: - // QGraphicsView::keyPressEvent(event); - break; - } - -// if (m_d->mode==PICK) { -// foreach (QGraphicsItem*item,items(event->pos())) { -// foreach(VP1GraphicsItemCollection* ic,m_d->cols_act) { -// if (ic->itemBelongsAndIsPresentlyActive(item)) { -// event->accept(); -// //EMIT [event] SIGNALS. -// } -// } -// } -// } - - - QGraphicsView::keyPressEvent(event); -} - -//____________________________________________________________________ -void VP1GraphicsView::setMode(const Mode& m) -{ - if (m_d->mode==m) - return; - m_d->mode=m; - if (m==PICK||m==CHANGEVIEW) - m_d->lastmajormode=m; - - if (m!=DRAGZOOM&&m!=DRAGZOOMHOLD) - m_d->dragzoom_startpoint=QPoint(); - - //Dragmode: - if (m==CHANGEVIEW) { - setDragMode(QGraphicsView::ScrollHandDrag); - } else { - setDragMode(QGraphicsView::NoDrag); - } - - //Cursor: - switch (m) { - case PICK: - setCursor(Qt::ArrowCursor); - break; - case CHANGEVIEW: - setCursor(Qt::OpenHandCursor); - break; - case DRAGZOOM: - case DRAGZOOMHOLD: - setCursor(Qt::SizeVerCursor); - break; - case SEEK: - setCursor(Qt::CrossCursor); - break; - default: - assert(0); - break; - } - - //Interactions/movable: - if (m==PICK) { - foreach (VP1GraphicsItemCollection*ic,m_d->cols_act) - if (!m_d->cols_override_inactive.contains(ic)) - ic->setTemporaryIgnoreInteractions(false); - foreach (VP1GraphicsItemCollection*ic,m_d->cols_all) - if (!m_d->cols_override_unmovable.contains(ic)) - ic->setTemporaryIgnoreMovable(false); - } else { - foreach (VP1GraphicsItemCollection*ic,m_d->cols_all) - ic->setTemporaryIgnoreMovable(true); - foreach (VP1GraphicsItemCollection*ic,m_d->cols_act) - ic->setTemporaryIgnoreInteractions(true); - } -} - -//____________________________________________________________________ -VP1GraphicsView::Mode VP1GraphicsView::mode() const -{ - return m_d->mode; -} - -//____________________________________________________________________ -void VP1GraphicsView::addItemCollection(VP1GraphicsItemCollection*ic) { - assert(!m_d->cols_all.contains(ic)); - assert(!m_d->cols_act.contains(ic)); - m_d->cols_all << ic; - if (ic->interactionMode()!=VP1GraphicsItemCollection::INERT) { - m_d->cols_act << ic; - ic->setTemporaryIgnoreInteractions( m_d->mode!=PICK || m_d->cols_override_inactive.contains(ic) ); - ic->setTemporaryIgnoreMovable( m_d->mode!=PICK || m_d->cols_override_unmovable.contains(ic) ); - } - ic->attachToView(this); -} - -//____________________________________________________________________ -void VP1GraphicsView::removeItemCollection(VP1GraphicsItemCollection*ic) { - assert(m_d->cols_all.contains(ic)); - m_d->cols_all.removeAll(ic); - if (m_d->cols_act.contains(ic)) - m_d->cols_act.removeAll(ic); - ic->setTemporaryIgnoreInteractions(false); - ic->setTemporaryIgnoreMovable(false); - ic->real_detachFromView(); - //Fixme: When user calls the detach/attach/... methods on the ic, these methods must also be invoked! - //Fixme: use groupnode in each ic. This also allows an easy hide/unhide action as well as z values... (ic have external setZValue() method). -} - -//____________________________________________________________________ -void VP1GraphicsView::mouseDoubleClickEvent(QMouseEvent * event) { - - if (m_d->showhelptext) { - m_d->showhelptext=false; - viewport()->update(); - }; - - if (m_d->mode!=PICK) { - QGraphicsView::mouseDoubleClickEvent(event); - return; - } - //Fixme: transformed pos - foreach (QGraphicsItem*item,items(event->pos())) { - foreach(VP1GraphicsItemCollection* ic,m_d->cols_act) { - if (ic->itemBelongsAndIsPresentlyActive(item)) { - event->accept(); - //EMIT SIGNALS. CHANGE SELECTION. - } - } - } - QGraphicsView::mouseDoubleClickEvent(event); - return; -} - - -//____________________________________________________________________ -void VP1GraphicsView::mouseMoveEvent(QMouseEvent *event) -{ - - //Fixme: transformed pos - - if ((m_d->mode==DRAGZOOM||m_d->mode==DRAGZOOMHOLD) && m_d->dragzoom_startpoint!=QPoint() ) { - double delta = event->pos().y()-m_d->dragzoom_startpoint.y(); - m_d->dragzoom_startpoint=event->pos(); - ViewportAnchor save = transformationAnchor(); - setTransformationAnchor(AnchorViewCenter); - scaleView(pow((double)2, -delta / (240.0/0.8)));//FIXME!! Dont have this equation more than once! - setTransformationAnchor(save); - event->accept(); - return; - } - if (m_d->mode==PICK) { - foreach (QGraphicsItem*item,items(event->pos())) { - foreach(VP1GraphicsItemCollection* ic,m_d->cols_act) { - if (ic->itemBelongsAndIsPresentlyActive(item)) { - event->accept(); - //EMIT [event] SIGNALS. - } - } - } - } - QGraphicsView::mouseMoveEvent(event); - return; -} - -//____________________________________________________________________ -void VP1GraphicsView::mousePressEvent(QMouseEvent *event) -{ - setFocus(Qt::MouseFocusReason);//Fixme: also doubleclick event! - - if (m_d->showhelptext) { - m_d->showhelptext=false; - viewport()->update(); - }; - - if (m_d->mode==SEEK) { - event->accept(); - setMode(m_d->lastmajormode); - seekToPoint(mapToScene(event->pos())); - return; - } - - if (m_d->mode==CHANGEVIEW&&event->buttons()==(Qt::LeftButton|Qt::MidButton)) { - event->accept(); - m_d->dragzoom_startpoint=event->pos(); - setMode(DRAGZOOM); - return; - } - - if (m_d->mode==DRAGZOOM&&event->buttons()!=(Qt::LeftButton|Qt::MidButton)) { - if (event->buttons()==(Qt::LeftButton|Qt::MidButton|Qt::RightButton)) { - setMode(DRAGZOOMHOLD); - } else { - setMode(CHANGEVIEW); - } - event->accept(); - return; - } - - if (m_d->mode==DRAGZOOMHOLD) {//Fixme: also doubleclick event! - setMode(CHANGEVIEW); - event->accept(); - return; - } - - - if (m_d->mode==PICK) { - if (event->buttons()!=Qt::LeftButton) { - QGraphicsView::mousePressEvent(event); - return; - } - //If we have previous selections already, and the mult select key - //is down, then we will only consider items in the same collection - //as active. - // std::cout<<"pick mouse press. Multiselection stored:"<<m_d->ic_multiselection<<std::endl; - bool continueselection = m_d->ic_multiselection && (event->modifiers() & Qt::ShiftModifier); - QGraphicsItem*item(0);VP1GraphicsItemCollection*ic(0); - -// QPoint pickpoint = m_d->transform ? -// mapFromScene(m_d->transform->inverseTransform( mapToScene(event->pos()))) -// : event->pos(); - QPoint pickpoint = event->pos(); - if (continueselection) { - assert(m_d->ic_multiselection); - m_d->locateActiveItemAtPoint(item,ic,pickpoint,m_d->ic_multiselection); - if (!item) { - //shift was down, and the user did not hit anything - QGraphicsView::mousePressEvent(event); - return; - } - } else { - m_d->locateActiveItemAtPoint(item,ic,pickpoint); - } - - if (item) { - assert(ic); - if (ic->interactionMode()==VP1GraphicsItemCollection::SINGLEPICKS) { - clearSelections(); - m_d->setNewSelected(item); - ic->itemPickedPrivate(item); - } else if (ic->interactionMode()==VP1GraphicsItemCollection::EVENTS) { - clearSelections(); - event->accept(); - ic->itemGotEventPrivate(item,event); - return; - } else if (ic->interactionMode()==VP1GraphicsItemCollection::SELECTIONS) { - assert(ic); - VP1GraphicsItemCollection * tmpic = ic; - m_d->ic_multiselection=ic; - m_d->setNewSelected(item,continueselection); - emitSelectionChanged(tmpic); - } else { - assert(0); - } - } else { - clearSelections(); - } - } - - QGraphicsView::mousePressEvent(event); - return; -} - -//____________________________________________________________________ -void VP1GraphicsView::mouseReleaseEvent(QMouseEvent *event) -{ - - //Fixme: transformed pos - if (m_d->mode==CHANGEVIEW&&event->buttons()==(Qt::LeftButton|Qt::MidButton)) { - event->accept(); - m_d->dragzoom_startpoint=event->pos(); - setMode(DRAGZOOM); - return; - } - - if (m_d->mode==DRAGZOOM&&event->buttons()!=(Qt::LeftButton|Qt::MidButton)) { - event->accept(); - setMode(CHANGEVIEW); - return; - } - - if (m_d->mode==PICK) { -// foreach (QGraphicsItem*item,items(event->pos())) { -// if (item==static_cast<QGraphicsItem*>(m_d->selectionoutline))//Fixme: Dont do the cast here. -// continue; -// foreach(VP1GraphicsItemCollection* ic,m_d->cols_act) { -// if (ic->itemBelongsAndIsPresentlyActive(item)) { -// event->accept(); -// if (ic->interactionMode()==VP1GraphicsItemCollection::EVENTS) { -// //EMIT EVENT SIGNAL! -// return; -// } -// if (m_d->selecteditem==item) { -// QGraphicsView::mouseReleaseEvent(event); -// return; -// } -// m_d->setNewSelected(item); -// //EMIT pick/selection signals. -// } -// } -// } - } - QGraphicsView::mouseReleaseEvent(event); - return; - -} - -//____________________________________________________________________ -void VP1GraphicsView::Imp::locateActiveItemAtPoint(QGraphicsItem*&item, - VP1GraphicsItemCollection*& ic, - const QPoint& pos, - VP1GraphicsItemCollection * searchic) { - - //We turn the point into a small circle - to get some chance of picking lines, degenerate rectangles, etc. - const double tol = 2.0; - QRectF tolrect( pos.x()-tol, pos.y()-tol, 2*tol, 2*tol ); - - QPainterPath p; - if (transform&&transformactive) { - QPainterPath ptmp; - ptmp.addEllipse(tolrect); - QPainterPath ptmp2; - transform->inverseTransformPath(view->mapToScene(ptmp),ptmp2); - QPainterPath p = view->mapFromScene(ptmp2); - } else { - p.addEllipse(tolrect); - } - - //Fixme: use faster stl style iterators. - foreach(QGraphicsItem* item2,view->items(p)) { - if (searchic) { - if (searchic->itemBelongsAndIsPresentlyActive(item2)) { - item=item2; - ic=searchic; - return; - } - } else { - foreach(VP1GraphicsItemCollection* ic2,cols_act) { - if (ic2->itemBelongsAndIsPresentlyActive(item2)) { - item=item2; - ic=ic2; - return; - } - } - } - } - assert(!item&&!ic); - return; -} - -//____________________________________________________________________ -void VP1GraphicsView::Imp::HighLightItemBeingDeleted(HighLightItem*hlitem) -{ - -#ifndef NDEBUG - QMapIterator<QGraphicsItem*,HighLightItem*> ittest(selecteditems); - assert(ittest.findNext(hlitem)); -#endif - - QMap<QGraphicsItem*,HighLightItem*>::iterator - it = selecteditems.begin(), itE = selecteditems.end(); - for (;it!=itE;++it) { - if (it.value()==hlitem) { - std::cout<<"lala1"<<std::endl; - selecteditems.erase(it); - std::cout<<"lala2"<<std::endl; - break; - } - } - std::cout<<"hej"<<std::endl; - - if (ic_multiselection) { - view->emitSelectionChanged(ic_multiselection); - } - std::cout<<"dav"<<std::endl; -#ifndef NDEBUG - QMapIterator<QGraphicsItem*,HighLightItem*> ittest2(selecteditems); - assert(!ittest2.findNext(hlitem)); -#endif -} - -//____________________________________________________________________ -void VP1GraphicsView::clearSelections() {//Fixme: only clear - //selections of certain - //collections? (so the - //permanent items stay - //selected?) - - bool haditemsinselection = m_d->ic_multiselection && !m_d->selecteditems.empty(); - - //Remove highlight items: - QMapIterator<QGraphicsItem*,HighLightItem*> it(m_d->selecteditems); - while (it.hasNext()) { - it.next(); - it.value()->sendsignalondelete = false; - //assert(!m_d->scene->items().contains(it.key())); - if (m_d->scene->items().contains(it.value())) { - m_d->scene->removeItem(it.value()); - // delete it.value(); - } - } - - //Clear lists - possibly emit a signal: - m_d->selecteditems.clear(); - if (m_d->clearselectionsemitsignals&&haditemsinselection) { - emitSelectionChanged(m_d->ic_multiselection); - m_d->ic_multiselection = 0;//TEST - } - m_d->clearselectionsemitsignals=true; -} - -//____________________________________________________________________ -void VP1GraphicsView::Imp::deselect(QGraphicsItem*item) -{ - if (selecteditems.count()==1) { - view->clearSelections(); - return; - } - - assert(selecteditems.contains(item)); - QMap<QGraphicsItem*,HighLightItem*>::iterator it = selecteditems.find(item); - if (scene->items().contains(it.value())) { - assert(scene->items().contains(it.value())); - scene->removeItem(it.value()); - it.value()->sendsignalondelete = false; - delete it.value(); - } - assert(selecteditems.contains(item)); - selecteditems.erase(it); - assert(!selecteditems.contains(item)); -} - -//____________________________________________________________________ -void VP1GraphicsView::Imp::select(QGraphicsItem*item) -{ - assert(!selecteditems.contains(item)); - - QPainterPath path = item->shape(); - - HighLightItem* outline = new HighLightItem(path,item,view); - outline->setBrush(QColor(250,0,250,100)); - outline->setPen(QPen(Qt::red,0,Qt::SolidLine,Qt::SquareCap,Qt::RoundJoin)); - scene->addItem(outline); - - selecteditems.insert(item,outline); - -} - -//____________________________________________________________________ -void VP1GraphicsView::Imp::setNewSelected(QGraphicsItem*item,const bool& continueselection) { - - assert(item); - - if (continueselection) { - if (selecteditems.contains(item)) - deselect(item); - else - select(item); - return; - } else { - if (!selecteditems.empty()) { - clearselectionsemitsignals=false; - view->clearSelections(); - } - select(item); - } - -// if (selecteditems.contains(item)) -// view->addselect(item); -// view->removeselect(item); - -// if (!continueselection&&!selecteditems.empty()) { -// view->clearSelections(); -// } - - -} - -//____________________________________________________________________ -void VP1GraphicsView::seekToPoint(QPointF targetpoint) { - abortZoomAnimation();//In case there is already an animation running we abort it. - QRectF currentview = mapToScene(viewport()->rect()).boundingRect(); - double w1= currentview.width(), h1= currentview.height(); - double w2 = w1/m_d->zoomfactoronseek, h2 = h1/m_d->zoomfactoronseek; - double x2 = targetpoint.x()-0.5*w2, y2 = targetpoint.y()-0.5*h2; - initiateAnimatedZoomTo( QRectF(x2,y2,w2,h2) ); -} - -//____________________________________________________________________ -void VP1GraphicsView::initiateAnimatedZoomTo( QRectF goal ) -{ - abortZoomAnimation(); - if (m_d->zoomanim_nsteps==1) { - fitInView(goal); - return; - } - - QRectF currentview = mapToScene(viewport()->rect()).boundingRect(); - - double w1 = currentview.width(), h1 = currentview.height(); - double x1 = currentview.x(), y1 = currentview.y(); - - double w2 = goal.width(), h2 = goal.height(); - double x2 = goal.x(), y2 = goal.y(); - - const double eps = 1.0/m_d->zoomanim_nsteps; - for (double f = eps; f < 1.0+0.5*eps; f+=eps ) { - //f values are spaced linearly between eps and 1.0. Let us - //construct something which has values packed closer near 1.0 (for - //that nice smooth slow-down feel): - double f2 = sqrt(f); - m_d->zoomanim_queue.enqueue(QRectF( x1*(1.0-f2)+x2*f2, y1*(1.0-f2)+y2*f2, - w1*(1.0-f2)+w2*f2, h1*(1.0-f2)+h2*f2 )); - } - - m_d->savedrenderhints=renderHints(); - setRenderHints(0); - m_d->zoomanim_timer->start(); -} - -//____________________________________________________________________ -void VP1GraphicsView::updateZoomAnimation() -{ - assert(!m_d->zoomanim_queue.empty()); - //For testing: - // QGraphicsRectItem * item = new QGraphicsRectItem(m_d->zoomanim_queue.dequeue()); - // item->setPen(QPen(Qt::blue,0,Qt::SolidLine,Qt::SquareCap,Qt::RoundJoin)); - // scene()->addItem(item); - fitInView( m_d->zoomanim_queue.dequeue(), Qt::KeepAspectRatio ); - if (m_d->zoomanim_queue.empty()) - m_d->zoomanim_timer->stop(); -} - -//____________________________________________________________________ -void VP1GraphicsView::abortZoomAnimation() -{ - if (m_d->zoomanim_timer->isActive()) - m_d->zoomanim_timer->stop(); - if (!m_d->zoomanim_queue.empty()) - m_d->zoomanim_queue.clear(); - if (m_d->savedrenderhints) - setRenderHints(m_d->savedrenderhints); - m_d->savedrenderhints=0;//Fixme: renderhints changed during an - //animation cycle might not be saved... Should - //override the renderhints methods to avoid - //this. -} - - -//____________________________________________________________________ -void VP1GraphicsView::setAnimatedZoomSteps( int n ) -{ - assert(n>=1); - m_d->zoomanim_nsteps = n; - m_d->zoomanim_timer->setInterval(std::max(1,static_cast<int>(m_d->zoomanim_totaltime/m_d->zoomanim_nsteps+0.5))); - //Same as just below. -} - -//____________________________________________________________________ -void VP1GraphicsView::setAnimatedZoomTime( double t ) -{ - m_d->zoomanim_totaltime = t; - m_d->zoomanim_timer->setInterval(std::max(1,static_cast<int>(m_d->zoomanim_totaltime/m_d->zoomanim_nsteps+0.5))); - //Same as just above. -} - -//____________________________________________________________________ -void VP1GraphicsView::setZoomFactorOnSeek( double zf ) -{ - m_d->zoomfactoronseek = zf; -} - -//____________________________________________________________________ -void VP1GraphicsView::viewHome() { - - const bool animatedhome = true;//Fixme: option? - if (m_d->home == QRect()) { - if (animatedhome) { - if (m_d->transform&&m_d->transformactive) - initiateAnimatedZoomTo(m_d->transform->transform(scene()->sceneRect())); - else - initiateAnimatedZoomTo(scene()->sceneRect()); - } else { - fitViewToContents(); - } - } else { - if (animatedhome) { - initiateAnimatedZoomTo(m_d->home); - } else { - fitInView( m_d->home, Qt::KeepAspectRatio ); - } - } -} - -//____________________________________________________________________ -void VP1GraphicsView::setHome() { - m_d->home=mapToScene(viewport()->rect()).boundingRect(); -} - -//____________________________________________________________________ -void VP1GraphicsView::emitSelectionChanged(VP1GraphicsItemCollection *ic) { - QList<QGraphicsItem*> emitlist = m_d->selecteditems.keys(); - if (emitlist==m_d->lastemittedselecteditems) - return; - m_d->lastemittedselecteditems=emitlist; - ic->selectionChangedPrivate(emitlist); -} - -//____________________________________________________________________ -void VP1GraphicsView::setDisallowInteractions(VP1GraphicsItemCollection*ic, const bool& disallow ) -{ - if (m_d->cols_override_inactive.contains(ic)==disallow) - return; - - if ( disallow ) { - m_d->cols_override_inactive.insert(ic); - if ( m_d->cols_all.contains(ic) ) - ic->setTemporaryIgnoreInteractions(true); - } else { - m_d->cols_override_inactive.remove(ic); - if ( m_d->cols_all.contains(ic) && m_d->mode != PICK ) - ic->setTemporaryIgnoreInteractions(false); - } -} - -//____________________________________________________________________ -void VP1GraphicsView::setDisallowMovable(VP1GraphicsItemCollection*ic, const bool& disallow ) -{ - if (m_d->cols_override_unmovable.contains(ic)==disallow) - return; - - if (disallow) { - m_d->cols_override_unmovable.insert(ic); - if (m_d->cols_all.contains(ic)) - ic->setTemporaryIgnoreMovable(true); - } else { - m_d->cols_override_unmovable.remove(ic); - if ( m_d->cols_all.contains(ic) && m_d->mode != PICK ) - ic->setTemporaryIgnoreMovable(false); - } -} - -//____________________________________________________________________ -void VP1GraphicsView::print() -{ - //Fixme: This does not really work well... Check again in QT 4.3? - QPrinter printer; - QPrintDialog dialog(&printer, this); - if (dialog.exec() == QDialog::Accepted) { - QPainter painter(&printer); - render(&painter); - } -} - -//____________________________________________________________________ -void VP1GraphicsView::saveImage() -{ - QString guess; - if (m_d->currentsaveimagefile.isEmpty()) { - QString base=VP1Settings::defaultFileSelectDirectory()+QDir::separator()+"vp1_capture"; - guess=base; - int i(2); - while (QFile::exists(guess+".png")) - guess=base+"_"+QString::number(i++); - guess+=".png"; - } else { - guess=m_d->currentsaveimagefile; - } - - QString filename = QFileDialog::getSaveFileName(0, "Select target image file", guess, - "Image (*.png *.bmp)", - 0,QFileDialog::DontResolveSymlinks); - if(filename.isEmpty()) - return; - - QPixmap pm = QPixmap::grabWidget ( viewport() ); - if (!(filename.endsWith(".png",Qt::CaseInsensitive)||filename.endsWith(".bmp",Qt::CaseInsensitive))) - filename += ".png"; - - pm.save(filename); - m_d->currentsaveimagefile = filename; -} - -// //____________________________________________________________________ -// void VP1GraphicsView::paintEvent ( QPaintEvent * event ) -// { -// //Fixme: Reimplementing the paintEvent like this is supposedly -// //helpful in some circumstances... I have not really benchmarked -// //whether it actually helps though... -// // QPaintEvent * newEvent = new QPaintEvent(event->region().boundingRect()); -// // QGraphicsView::paintEvent(newEvent); -// // delete newEvent; -// } - -//____________________________________________________________________ -void VP1GraphicsView::drawForeground ( QPainter * painter, const QRectF & /*rect*/ ) { - - //Fixme: use rect? - if (!m_d->showhelptext) - return; - QRect imgrect = viewport()->rect(); - imgrect.setWidth(imgrect.width()*3); - imgrect.setHeight(imgrect.height()*3); - if (!m_d->helptextimage||m_d->helptextimage->size()!=imgrect.size()) - m_d->createNewHelptextImage(imgrect);//viewport()->rect()); - painter->setRenderHint(QPainter::Antialiasing, false); - painter->drawImage(mapToScene(viewport()->rect()).boundingRect(),*(m_d->helptextimage), - imgrect); -} - -//____________________________________________________________________ -void VP1GraphicsView::Imp::createNewHelptextImage(const QRect& imrect) -{ - if(helptext.isEmpty()) { - helptext.setHtml ("<html>\n" - "\n" - "<h2>How to navigate a VP1GraphicsView</h2>\n" - "\n" - " <p>\n <b>H/F1</b> Show this help." - " \n <b>S</b> Seek mode.\n" - " \n <b>+/-</b> Zoom.\n" - " \n <b>CTRL+HOME</b> Set home.\n" - " \n <b>HOME</b> View home.\n" - " \n <b>1</b> View all.\n" - " \n <b>ESC</b> Switch between view and pick mode.\n" - " \n <b>P</b> Print view.\n" - " \n <b>CTRL+P</b> Save snapshot to image file.</p>\n" - " <p>\n <b>Mouse wheel</b> zoom. Use <b>CTRL</b> and <b>SHIFT</b> for finegrained control.</p>\n" - " <p>\n To select items (in pick mode), click on them. Selected multiple by holding down <b>SHIFT</b>.</p>\n" - "\n" - "<p>\n" - " Please report any bugs to <i>Thomas.Kittelmann@cern.ch</i>.\n" - "</p>\n" - "\n" - "\n" - "</html>" ); - QFont myfont("Helvetica",36); - // myfont.setPointSize(400); - helptext.setDefaultFont ( myfont ); - // helptext.defaultFont().setPointSize(400); - } - - delete helptextimage; - helptextimage = new QImage(imrect.size(), QImage::Format_ARGB32);//Fixme delete in destructor!! - - QPainter painter; - painter.begin(helptextimage); - - int pageWidth = qMax(imrect.width() - 100, 100); - int pageHeight = qMax(imrect.height() - 100, 100); - if (pageWidth != helptext.pageSize().width()) { - helptext.setPageSize(QSize(pageWidth, pageHeight)); - } - - QRect textRect(imrect.width() / 2 - pageWidth / 2, - imrect.height() / 2 - pageHeight / 2, - pageWidth, - pageHeight); - int pad = 10; - QRect clearRect = textRect.adjusted(-pad, -pad, pad, pad); - painter.setPen(Qt::NoPen); - painter.setBrush(QColor(0, 0, 0, 63)); - int shade = 10; - painter.drawRect(clearRect.x() + clearRect.width() + 1, - clearRect.y() + shade, - shade, - clearRect.height() + 1); - painter.drawRect(clearRect.x() + shade, - clearRect.y() + clearRect.height() + 1, - clearRect.width() - shade + 1, - shade); - - painter.setRenderHint(QPainter::Antialiasing, false); - painter.setBrush(QColor(255, 255, 255, 220)); - painter.setPen(Qt::black); - painter.drawRect(clearRect); - - painter.setClipRegion(textRect, Qt::IntersectClip); - painter.translate(textRect.topLeft()); - - QAbstractTextDocumentLayout::PaintContext ctx; - - QLinearGradient g(0, 0, 0, textRect.height()); - g.setColorAt(0, Qt::black); - g.setColorAt(0.9, Qt::black); - g.setColorAt(1, Qt::transparent); - - QPalette pal = view->viewport()->palette(); - pal.setBrush(QPalette::Text, g); - - ctx.palette = pal; - ctx.clip = QRect(0, 0, textRect.width(), textRect.height()); - helptext.documentLayout()->draw(&painter, ctx); - - painter.end(); - -} - -//____________________________________________________________________ -void VP1GraphicsView::drawItems(QPainter *painter, int numItems, - QGraphicsItem *items[], - const QStyleOptionGraphicsItem options[]) -{ - - if (!(m_d->transform&&m_d->transformactive)) { - QGraphicsView::drawItems(painter,numItems,items,options); - //Fixme: implement own drawing here also - to make sure inbuilt selection stuff is never shown? - return; - } - - for (int i = 0; i < numItems; ++i) { - QGraphicsItem *item = items[i]; - painter->save(); - painter->setMatrix(item->sceneMatrix(), true);//?? - // std::cout<< item->sceneMatrix().isIdentity()<<std::endl; - // std::cout<< item->sceneMatrix().dx()<<" : "<<item->sceneMatrix().dy()<<std::endl; - m_d->transform->paintItem(painter, item); - painter->restore(); - } -} diff --git a/GeoModelVisualization/VP1Base/src/VP1MaterialButton.cxx b/GeoModelVisualization/VP1Base/src/VP1MaterialButton.cxx index 929fb13c504f26a929984bcbc4c2f589e05bea6f..69cbbcf17c06e671a9a133690c136e00cfffde0b 100644 --- a/GeoModelVisualization/VP1Base/src/VP1MaterialButton.cxx +++ b/GeoModelVisualization/VP1Base/src/VP1MaterialButton.cxx @@ -327,6 +327,10 @@ void VP1MaterialButton::Imp::initEditWindow() editwindow_ui.label_num_simple_brightness->setNum(lastapplied_brightness); editwindow_ui.colbutton_simple_colour->setColor(lastapplied_diffuse); + QObject::connect(editwindow_ui.slider_shininess, SIGNAL(valueChanged (int)), editwindow_ui.label_num_shininess, SLOT(setNum(int))); + QObject::connect(editwindow_ui.slider_simple_brightness, SIGNAL(valueChanged(int)), editwindow_ui.label_num_simple_brightness, SLOT(setNum(int))); + + #if defined BUILDVP1LIGHT bool checkDisallowMultipleChannels = VP1QtUtils::expertSettingIsOn("general","ExpertSettings/VP1_DISALLOW_MULTIPLE_CHANNELS"); #else diff --git a/GeoModelVisualization/VP1Base/src/VP1QtInventorUtils.cxx b/GeoModelVisualization/VP1Base/src/VP1QtInventorUtils.cxx index 3ad0dd37918f415893ac03386271591bdf885670..e89ee75e2678ec68df3aaaf06b41070a997f620e 100644 --- a/GeoModelVisualization/VP1Base/src/VP1QtInventorUtils.cxx +++ b/GeoModelVisualization/VP1Base/src/VP1QtInventorUtils.cxx @@ -46,7 +46,7 @@ #include <QByteArray> #include <QTextStream> #include <QSlider> -#include <QGLFormat> +//#include <QGLFormat> #include <iostream> @@ -522,11 +522,11 @@ QImage VP1QtInventorUtils::renderToImage(VP1ExaminerViewer *ra, int pixels_x, in myViewport.setWindowSize(SbVec2s(pixels_x,pixels_y)); // init the random number generator a get a random filename for the temp file - qsrand(QTime::currentTime().msecsTo(QTime(0,0))); + srand(QTime::currentTime().msecsTo(QTime(0,0))); QString tmppath(QDir::tempPath()); if (!tmppath.endsWith(QDir::separator())) tmppath+=QDir::separator(); - QString tmpfile = tmppath+"vp1tmpfile" +QString::number(qrand())+QString::number(qrand())+".rgb"; + QString tmpfile = tmppath+"vp1tmpfile" +QString::number(rand())+QString::number(rand())+".rgb"; // declare a new renderer with the viewport created above SoOffscreenRenderer *myRenderer = new SoOffscreenRenderer(myViewport); @@ -1434,7 +1434,7 @@ bool VP1QtInventorUtils::writeGraphToFile(SoNode*root, const QString& filename) QFile data(filename); if (data.open(QFile::WriteOnly | QFile::Truncate)) { QTextStream out(&data); - out << s << endl; + out << s << Qt::endl; return true; } else { return false; diff --git a/GeoModelVisualization/VP1Base/src/VP1TabBar.cxx b/GeoModelVisualization/VP1Base/src/VP1TabBar.cxx index 5b9a63ea69833beedc226cbbe93462e78a3c8f60..7e40294ed8a05d6126029580b7a3a0b0645355c8 100644 --- a/GeoModelVisualization/VP1Base/src/VP1TabBar.cxx +++ b/GeoModelVisualization/VP1Base/src/VP1TabBar.cxx @@ -133,7 +133,7 @@ void VP1TabBar::mouseMoveEvent( QMouseEvent *event ) return; } } - } else if ( event->buttons() == Qt::MidButton ) { + } else if ( event->buttons() == Qt::MiddleButton ) { if ( m_d->mReorderStartTab == -1 ) { int delay = 5;//TK fixme KGlobalSettings::dndEventDelay(); QPoint newPos = event->pos(); @@ -178,7 +178,7 @@ void VP1TabBar::activateDragSwitchTab() void VP1TabBar::mouseReleaseEvent( QMouseEvent *event ) { - if ( event->button() == Qt::MidButton ) { + if ( event->button() == Qt::MiddleButton ) { if ( m_d->mReorderStartTab == -1 ) { int tab = selectTab( event->pos() ); if ( tab != -1 ) { @@ -239,10 +239,7 @@ void VP1TabBar::dropEvent( QDropEvent *event ) #ifndef QT_NO_WHEELEVENT void VP1TabBar::wheelEvent( QWheelEvent *event ) { - if ( event->orientation() == Qt::Horizontal ) - return; - - emit( wheelDelta( event->delta() ) ); + emit( wheelDelta( event->pixelDelta().x() ) ); } #endif diff --git a/GeoModelVisualization/VP1Base/src/VP1TabWidget.cxx b/GeoModelVisualization/VP1Base/src/VP1TabWidget.cxx index b2e2bb470d82314edb106de4ba78afdb6d8900da..8ce7ed0daac5810691bff3f4c4685eda74695de4 100644 --- a/GeoModelVisualization/VP1Base/src/VP1TabWidget.cxx +++ b/GeoModelVisualization/VP1Base/src/VP1TabWidget.cxx @@ -274,13 +274,13 @@ int VP1TabWidget::tabBarWidthForMaxChars( int /*maxLength*/ ) //TK-fixme. Just use elide here? //TK-fixme newTitle = KStringHandler::rsqueeze( newTitle, maxLength ).leftJustified( m_d->m_minLength, ' ' ); - int lw = fm.width( newTitle ); + int lw = fm.boundingRect( newTitle ).width(); int iw = 0; if ( !tabBar()->tabIcon( i ).isNull() ){ iw = tabBar()->tabIcon( i ).pixmap( style()->pixelMetric( QStyle::PM_SmallIconSize ), QIcon::Normal ).width() + 4; } x += ( tabBar()->style()->sizeFromContents( QStyle::CT_TabBarTab, 0L, - QSize( qMax( lw + hframe + iw, QApplication::globalStrut().width() ), 0 ), + QSize(lw + hframe + iw, 0 ), this ) ).width(); } @@ -346,11 +346,9 @@ void VP1TabWidget::dropEvent( QDropEvent *event ) #ifndef QT_NO_WHEELEVENT void VP1TabWidget::wheelEvent( QWheelEvent *event ) { - if ( event->orientation() == Qt::Horizontal ) - return; - if ( m_d->isEmptyTabbarSpace( event->pos() ) ) - wheelDelta( event->delta() ); + if ( m_d->isEmptyTabbarSpace(event->position().toPoint() ) ) + wheelDelta( event->pixelDelta().x() ); else event->ignore(); } @@ -392,7 +390,7 @@ void VP1TabWidget::mousePressEvent( QMouseEvent *event ) emit( contextMenu( mapToGlobal( event->pos() ) ) ); return; } - } else if ( event->button() == Qt::MidButton ) { + } else if ( event->button() == Qt::MiddleButton ) { if ( m_d->isEmptyTabbarSpace( event->pos() ) ) { emit( mouseMiddleClick() ); return; diff --git a/GeoModelVisualization/VP1Base/src/vp1materialbuttonform.ui b/GeoModelVisualization/VP1Base/src/vp1materialbuttonform.ui index 60d143485e85cd2bf5a0489d2c3cf86299d43e34..6012d89b7bcfb75aad5caec516bd57ba8deed8a3 100644 --- a/GeoModelVisualization/VP1Base/src/vp1materialbuttonform.ui +++ b/GeoModelVisualization/VP1Base/src/vp1materialbuttonform.ui @@ -1,58 +1,59 @@ -<ui version="4.0" > +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> <class>VP1MaterialButtonForm</class> - <widget class="QWidget" name="VP1MaterialButtonForm" > - <property name="geometry" > + <widget class="QWidget" name="VP1MaterialButtonForm"> + <property name="geometry"> <rect> <x>0</x> <y>0</y> - <width>545</width> + <width>580</width> <height>292</height> </rect> </property> - <property name="windowTitle" > + <property name="windowTitle"> <string>Edit Material</string> </property> - <layout class="QVBoxLayout" > + <layout class="QVBoxLayout"> <item> - <layout class="QGridLayout" > - <item row="0" column="0" > - <widget class="QStackedWidget" name="stackedWidget" > - <property name="currentIndex" > - <number>0</number> + <layout class="QGridLayout"> + <item row="0" column="0"> + <widget class="QStackedWidget" name="stackedWidget"> + <property name="currentIndex"> + <number>1</number> </property> - <widget class="QWidget" name="page_simple" > - <layout class="QVBoxLayout" > + <widget class="QWidget" name="page_simple"> + <layout class="QVBoxLayout"> <item> - <layout class="QHBoxLayout" > + <layout class="QHBoxLayout"> <item> - <widget class="QLabel" name="label_10" > - <property name="toolTip" > + <widget class="QLabel" name="label_10"> + <property name="toolTip"> <string>Material colour</string> </property> - <property name="text" > + <property name="text"> <string>Colo&ur:</string> </property> - <property name="buddy" > + <property name="buddy"> <cstring>colbutton_simple_colour</cstring> </property> </widget> </item> <item> - <widget class="VP1ColorSelectButton" name="colbutton_simple_colour" > - <property name="toolTip" > + <widget class="VP1ColorSelectButton" name="colbutton_simple_colour"> + <property name="toolTip"> <string>Material colour</string> </property> - <property name="text" > + <property name="text"> <string/> </property> </widget> </item> <item> <spacer> - <property name="orientation" > + <property name="orientation"> <enum>Qt::Horizontal</enum> </property> - <property name="sizeHint" > + <property name="sizeHint" stdset="0"> <size> <width>40</width> <height>20</height> @@ -63,123 +64,123 @@ </layout> </item> <item> - <layout class="QGridLayout" > - <item row="0" column="1" > - <widget class="QSlider" name="slider_simple_brightness" > - <property name="sizePolicy" > - <sizepolicy vsizetype="Fixed" hsizetype="Fixed" > + <layout class="QGridLayout"> + <item row="0" column="1"> + <widget class="QSlider" name="slider_simple_brightness"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <property name="minimumSize" > + <property name="minimumSize"> <size> <width>120</width> <height>0</height> </size> </property> - <property name="toolTip" > + <property name="toolTip"> <string>Material brightness</string> </property> - <property name="maximum" > + <property name="maximum"> <number>100</number> </property> - <property name="value" > + <property name="value"> <number>20</number> </property> - <property name="orientation" > + <property name="orientation"> <enum>Qt::Horizontal</enum> </property> </widget> </item> - <item row="0" column="2" > - <widget class="QLabel" name="label_num_simple_brightness" > - <property name="minimumSize" > + <item row="0" column="2"> + <widget class="QLabel" name="label_num_simple_brightness"> + <property name="minimumSize"> <size> <width>20</width> <height>0</height> </size> </property> - <property name="toolTip" > + <property name="toolTip"> <string>Material brightness</string> </property> - <property name="text" > + <property name="text"> <string>20</string> </property> - <property name="alignment" > + <property name="alignment"> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> </property> </widget> </item> - <item row="1" column="0" > - <widget class="QLabel" name="label_15" > - <property name="toolTip" > + <item row="1" column="0"> + <widget class="QLabel" name="label_15"> + <property name="toolTip"> <string>Transparency of the material</string> </property> - <property name="text" > + <property name="text"> <string>&Transparency:</string> </property> - <property name="buddy" > + <property name="buddy"> <cstring>slider_simple_transparency</cstring> </property> </widget> </item> - <item row="1" column="1" > - <widget class="QSlider" name="slider_simple_transparency" > - <property name="sizePolicy" > - <sizepolicy vsizetype="Fixed" hsizetype="Fixed" > + <item row="1" column="1"> + <widget class="QSlider" name="slider_simple_transparency"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <property name="minimumSize" > + <property name="minimumSize"> <size> <width>120</width> <height>0</height> </size> </property> - <property name="toolTip" > + <property name="toolTip"> <string>Transparency of the material</string> </property> - <property name="maximum" > + <property name="maximum"> <number>100</number> </property> - <property name="value" > + <property name="value"> <number>0</number> </property> - <property name="orientation" > + <property name="orientation"> <enum>Qt::Horizontal</enum> </property> </widget> </item> - <item row="1" column="2" > - <widget class="QLabel" name="label_num_simple_transparency" > - <property name="minimumSize" > + <item row="1" column="2"> + <widget class="QLabel" name="label_num_simple_transparency"> + <property name="minimumSize"> <size> <width>20</width> <height>0</height> </size> </property> - <property name="toolTip" > + <property name="toolTip"> <string>Transparency of the material</string> </property> - <property name="text" > + <property name="text"> <string>0</string> </property> - <property name="alignment" > + <property name="alignment"> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> </property> </widget> </item> - <item row="0" column="0" > - <widget class="QLabel" name="label_13" > - <property name="toolTip" > + <item row="0" column="0"> + <widget class="QLabel" name="label_13"> + <property name="toolTip"> <string>Material brightness</string> </property> - <property name="text" > + <property name="text"> <string>Br&ightness:</string> </property> - <property name="buddy" > + <property name="buddy"> <cstring>slider_simple_brightness</cstring> </property> </widget> @@ -188,10 +189,10 @@ </item> <item> <spacer> - <property name="orientation" > + <property name="orientation"> <enum>Qt::Vertical</enum> </property> - <property name="sizeHint" > + <property name="sizeHint" stdset="0"> <size> <width>20</width> <height>20</height> @@ -201,100 +202,100 @@ </item> </layout> </widget> - <widget class="QWidget" name="page_detailed" > - <layout class="QVBoxLayout" > + <widget class="QWidget" name="page_detailed"> + <layout class="QVBoxLayout"> <item> - <layout class="QHBoxLayout" > + <layout class="QHBoxLayout"> <item> - <layout class="QGridLayout" > - <item row="0" column="0" > - <widget class="QLabel" name="label_3" > - <property name="toolTip" > + <layout class="QGridLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="label_3"> + <property name="toolTip"> <string>Base colour of the material.</string> </property> - <property name="text" > + <property name="text"> <string>D&iffuse colour:</string> </property> - <property name="buddy" > + <property name="buddy"> <cstring>colbutton_diffuse</cstring> </property> </widget> </item> - <item row="0" column="1" > - <widget class="VP1ColorSelectButton" name="colbutton_diffuse" > - <property name="toolTip" > + <item row="0" column="1"> + <widget class="VP1ColorSelectButton" name="colbutton_diffuse"> + <property name="toolTip"> <string>Base colour of the material.</string> </property> - <property name="text" > + <property name="text"> <string/> </property> </widget> </item> - <item row="1" column="0" > - <widget class="QLabel" name="label_5" > - <property name="toolTip" > + <item row="1" column="0"> + <widget class="QLabel" name="label_5"> + <property name="toolTip"> <string>Reflected colour in response to the ambient lighting in the scene</string> </property> - <property name="text" > + <property name="text"> <string>A&mbient colour:</string> </property> - <property name="buddy" > + <property name="buddy"> <cstring>colbutton_ambient</cstring> </property> </widget> </item> - <item row="1" column="1" > - <widget class="VP1ColorSelectButton" name="colbutton_ambient" > - <property name="toolTip" > + <item row="1" column="1"> + <widget class="VP1ColorSelectButton" name="colbutton_ambient"> + <property name="toolTip"> <string>Reflected colour in response to the ambient lighting in the scene</string> </property> - <property name="text" > + <property name="text"> <string/> </property> </widget> </item> - <item row="2" column="0" > - <widget class="QLabel" name="label_8" > - <property name="toolTip" > + <item row="2" column="0"> + <widget class="QLabel" name="label_8"> + <property name="toolTip"> <string>Reflective quality of highlights</string> </property> - <property name="text" > + <property name="text"> <string>S&pecular colour:</string> </property> - <property name="buddy" > + <property name="buddy"> <cstring>colbutton_specular</cstring> </property> </widget> </item> - <item row="2" column="1" > - <widget class="VP1ColorSelectButton" name="colbutton_specular" > - <property name="toolTip" > + <item row="2" column="1"> + <widget class="VP1ColorSelectButton" name="colbutton_specular"> + <property name="toolTip"> <string>Reflective quality of highlights</string> </property> - <property name="text" > + <property name="text"> <string/> </property> </widget> </item> - <item row="3" column="0" > - <widget class="QLabel" name="label_9" > - <property name="toolTip" > + <item row="3" column="0"> + <widget class="QLabel" name="label_9"> + <property name="toolTip"> <string>Colour emitted by the material</string> </property> - <property name="text" > + <property name="text"> <string>&Emissive colour:</string> </property> - <property name="buddy" > + <property name="buddy"> <cstring>colbutton_emissive</cstring> </property> </widget> </item> - <item row="3" column="1" > - <widget class="VP1ColorSelectButton" name="colbutton_emissive" > - <property name="toolTip" > + <item row="3" column="1"> + <widget class="VP1ColorSelectButton" name="colbutton_emissive"> + <property name="toolTip"> <string>Colour emitted by the material</string> </property> - <property name="text" > + <property name="text"> <string/> </property> </widget> @@ -303,10 +304,10 @@ </item> <item> <spacer> - <property name="orientation" > + <property name="orientation"> <enum>Qt::Horizontal</enum> </property> - <property name="sizeHint" > + <property name="sizeHint" stdset="0"> <size> <width>20</width> <height>20</height> @@ -317,123 +318,123 @@ </layout> </item> <item> - <layout class="QGridLayout" > - <item row="0" column="0" > - <widget class="QLabel" name="label" > - <property name="toolTip" > + <layout class="QGridLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="toolTip"> <string>Degree of shininess, ranging from 0 for a diffuse surface with no shininess to 100 for a highly polished surface</string> </property> - <property name="text" > + <property name="text"> <string>S&hininess:</string> </property> - <property name="buddy" > + <property name="buddy"> <cstring>slider_shininess</cstring> </property> </widget> </item> - <item row="0" column="1" > - <widget class="QSlider" name="slider_shininess" > - <property name="sizePolicy" > - <sizepolicy vsizetype="Fixed" hsizetype="Fixed" > + <item row="0" column="1"> + <widget class="QSlider" name="slider_shininess"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <property name="minimumSize" > + <property name="minimumSize"> <size> <width>120</width> <height>0</height> </size> </property> - <property name="toolTip" > + <property name="toolTip"> <string>Degree of shininess, ranging from 0 for a diffuse surface with no shininess to 100 for a highly polished surface</string> </property> - <property name="maximum" > + <property name="maximum"> <number>100</number> </property> - <property name="value" > + <property name="value"> <number>20</number> </property> - <property name="orientation" > + <property name="orientation"> <enum>Qt::Horizontal</enum> </property> </widget> </item> - <item row="0" column="2" > - <widget class="QLabel" name="label_num_shininess" > - <property name="minimumSize" > + <item row="0" column="2"> + <widget class="QLabel" name="label_num_shininess"> + <property name="minimumSize"> <size> <width>20</width> <height>0</height> </size> </property> - <property name="toolTip" > + <property name="toolTip"> <string>Degree of shininess, ranging from 0 for a diffuse surface with no shininess to 100 for a highly polished surface</string> </property> - <property name="text" > + <property name="text"> <string>20</string> </property> - <property name="alignment" > + <property name="alignment"> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> </property> </widget> </item> - <item row="1" column="0" > - <widget class="QLabel" name="label_2" > - <property name="toolTip" > + <item row="1" column="0"> + <widget class="QLabel" name="label_2"> + <property name="toolTip"> <string>Transparency of the material</string> </property> - <property name="text" > + <property name="text"> <string>&Transparency:</string> </property> - <property name="buddy" > + <property name="buddy"> <cstring>slider_transparency</cstring> </property> </widget> </item> - <item row="1" column="1" > - <widget class="QSlider" name="slider_transparency" > - <property name="sizePolicy" > - <sizepolicy vsizetype="Fixed" hsizetype="Fixed" > + <item row="1" column="1"> + <widget class="QSlider" name="slider_transparency"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <property name="minimumSize" > + <property name="minimumSize"> <size> <width>120</width> <height>0</height> </size> </property> - <property name="toolTip" > + <property name="toolTip"> <string>Transparency of the material</string> </property> - <property name="maximum" > + <property name="maximum"> <number>100</number> </property> - <property name="value" > + <property name="value"> <number>0</number> </property> - <property name="orientation" > + <property name="orientation"> <enum>Qt::Horizontal</enum> </property> </widget> </item> - <item row="1" column="2" > - <widget class="QLabel" name="label_num_transparency" > - <property name="minimumSize" > + <item row="1" column="2"> + <widget class="QLabel" name="label_num_transparency"> + <property name="minimumSize"> <size> <width>20</width> <height>0</height> </size> </property> - <property name="toolTip" > + <property name="toolTip"> <string>Transparency of the material</string> </property> - <property name="text" > + <property name="text"> <string>0</string> </property> - <property name="alignment" > + <property name="alignment"> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> </property> </widget> @@ -444,15 +445,15 @@ </widget> </widget> </item> - <item row="0" column="1" > + <item row="0" column="1"> <spacer> - <property name="orientation" > + <property name="orientation"> <enum>Qt::Horizontal</enum> </property> - <property name="sizeType" > + <property name="sizeType"> <enum>QSizePolicy::Fixed</enum> </property> - <property name="sizeHint" > + <property name="sizeHint" stdset="0"> <size> <width>16</width> <height>20</height> @@ -460,9 +461,9 @@ </property> </spacer> </item> - <item row="0" column="2" > - <widget class="QWidget" native="1" name="widget_3dpreview" > - <property name="minimumSize" > + <item row="0" column="2"> + <widget class="QWidget" name="widget_3dpreview" native="true"> + <property name="minimumSize"> <size> <width>200</width> <height>200</height> @@ -470,54 +471,54 @@ </property> </widget> </item> - <item row="1" column="2" > - <layout class="QHBoxLayout" > + <item row="1" column="2"> + <layout class="QHBoxLayout"> <item> - <widget class="QLabel" name="label_4" > - <property name="text" > + <widget class="QLabel" name="label_4"> + <property name="text"> <string>Preview:</string> </property> </widget> </item> <item> - <widget class="QRadioButton" name="radioButton_cone" > - <property name="toolTip" > + <widget class="QRadioButton" name="radioButton_cone"> + <property name="toolTip"> <string>Use a cone for the preview above</string> </property> - <property name="text" > + <property name="text"> <string>C&one</string> </property> </widget> </item> <item> - <widget class="QRadioButton" name="radioButton_box" > - <property name="toolTip" > + <widget class="QRadioButton" name="radioButton_box"> + <property name="toolTip"> <string>Use a box for the preview above</string> </property> - <property name="text" > + <property name="text"> <string>&Box</string> </property> </widget> </item> <item> - <widget class="QRadioButton" name="radioButton_lines" > - <property name="toolTip" > + <widget class="QRadioButton" name="radioButton_lines"> + <property name="toolTip"> <string>Use lines for the preview above</string> </property> - <property name="text" > + <property name="text"> <string>&Lines</string> </property> </widget> </item> <item> <spacer> - <property name="orientation" > + <property name="orientation"> <enum>Qt::Horizontal</enum> </property> - <property name="sizeType" > + <property name="sizeType"> <enum>QSizePolicy::MinimumExpanding</enum> </property> - <property name="sizeHint" > + <property name="sizeHint" stdset="0"> <size> <width>1</width> <height>20</height> @@ -531,10 +532,10 @@ </item> <item> <spacer> - <property name="orientation" > + <property name="orientation"> <enum>Qt::Vertical</enum> </property> - <property name="sizeHint" > + <property name="sizeHint" stdset="0"> <size> <width>527</width> <height>16</height> @@ -543,20 +544,20 @@ </spacer> </item> <item> - <layout class="QHBoxLayout" > + <layout class="QHBoxLayout"> <item> - <widget class="QPushButton" name="pushButton_switch_mode" > - <property name="text" > + <widget class="QPushButton" name="pushButton_switch_mode"> + <property name="text"> <string>&Switch to xxxxxx mode</string> </property> </widget> </item> <item> <spacer> - <property name="orientation" > + <property name="orientation"> <enum>Qt::Horizontal</enum> </property> - <property name="sizeHint" > + <property name="sizeHint" stdset="0"> <size> <width>40</width> <height>20</height> @@ -565,31 +566,31 @@ </spacer> </item> <item> - <widget class="QPushButton" name="pushButton_apply" > - <property name="toolTip" > + <widget class="QPushButton" name="pushButton_apply"> + <property name="toolTip"> <string>Apply current settings</string> </property> - <property name="text" > + <property name="text"> <string>&Apply</string> </property> </widget> </item> <item> - <widget class="QPushButton" name="pushButton_reset" > - <property name="toolTip" > + <widget class="QPushButton" name="pushButton_reset"> + <property name="toolTip"> <string>Reset to last applied settings</string> </property> - <property name="text" > + <property name="text"> <string>&Reset</string> </property> </widget> </item> <item> - <widget class="QPushButton" name="pushButton_close" > - <property name="toolTip" > + <widget class="QPushButton" name="pushButton_close"> + <property name="toolTip"> <string>Close material editor [Esc]</string> </property> - <property name="text" > + <property name="text"> <string>&Close</string> </property> </widget> @@ -625,53 +626,21 @@ </tabstops> <resources/> <connections> - <connection> - <sender>slider_shininess</sender> - <signal>valueChanged(int)</signal> - <receiver>label_num_shininess</receiver> - <slot>setNum(int)</slot> - <hints> - <hint type="sourcelabel" > - <x>213</x> - <y>171</y> - </hint> - <hint type="destinationlabel" > - <x>231</x> - <y>175</y> - </hint> - </hints> - </connection> <connection> <sender>pushButton_close</sender> <signal>clicked()</signal> <receiver>VP1MaterialButtonForm</receiver> <slot>hide()</slot> <hints> - <hint type="sourcelabel" > + <hint type="sourcelabel"> <x>534</x> <y>285</y> </hint> - <hint type="destinationlabel" > + <hint type="destinationlabel"> <x>544</x> <y>265</y> </hint> </hints> </connection> - <connection> - <sender>slider_simple_brightness</sender> - <signal>valueChanged(int)</signal> - <receiver>label_num_simple_brightness</receiver> - <slot>setNum(int)</slot> - <hints> - <hint type="sourcelabel" > - <x>177</x> - <y>64</y> - </hint> - <hint type="destinationlabel" > - <x>223</x> - <y>68</y> - </hint> - </hints> - </connection> </connections> </ui> diff --git a/GeoModelVisualization/VP1GeometryPlugin/CMakeLists.txt b/GeoModelVisualization/VP1GeometryPlugin/CMakeLists.txt index 4f4889e36606dc321efec033e86e9ebc295dec5f..488841c6cf9c6a1a9bc195155b330ef233ad21b4 100644 --- a/GeoModelVisualization/VP1GeometryPlugin/CMakeLists.txt +++ b/GeoModelVisualization/VP1GeometryPlugin/CMakeLists.txt @@ -7,7 +7,7 @@ file( GLOB HEADERS VP1GeometryPlugin/*.h ) # Add the library. add_library( GXGeometryPlugin MODULE ${SOURCES} ${HEADERS} ) target_link_libraries( GXGeometryPlugin - PUBLIC Qt5::Core GXBase + PUBLIC Qt${QT_VERSION}::Core GXBase PRIVATE GXGeometrySystems GXGuideLineSystems GXClashPointSystems GXHitDisplaySystems GXTrackDisplaySystems) target_include_directories( GXGeometryPlugin PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> diff --git a/GeoModelVisualization/VP1GeometrySystems/CMakeLists.txt b/GeoModelVisualization/VP1GeometrySystems/CMakeLists.txt index fb3e73d64870e9b3c24110ddd20600ce518daf32..a912560a308193c94e82447bcd5d3dc301478962 100644 --- a/GeoModelVisualization/VP1GeometrySystems/CMakeLists.txt +++ b/GeoModelVisualization/VP1GeometrySystems/CMakeLists.txt @@ -9,7 +9,7 @@ file( GLOB DATA share/*.jpg share/*.json ) # Add the library. add_library( GXGeometrySystems SHARED ${SOURCES} ${HEADERS} ${UIS} ) target_link_libraries( GXGeometrySystems - PUBLIC Coin::Coin Qt5::Core Qt5::Gui Qt5::Widgets + PUBLIC Coin::Coin Qt${QT_VERSION}::Core Qt${QT_VERSION}::Gui Qt${QT_VERSION}::Widgets GeoModelCore::GeoModelKernel GXBase PRIVATE nlohmann_json::nlohmann_json GeoModelIO::GeoModelRead GeoModelIO::GeoModelWrite GeoModelIO::GeoModelDBManager GXHEPVis ) @@ -26,9 +26,6 @@ set_target_properties( GXGeometrySystems PROPERTIES if( GEOMODEL_USE_BUILTIN_COIN3D ) add_dependencies( GXGeometrySystems Coin3DBuiltIn ) endif() -if( GEOMODEL_USE_BUILTIN_JSON ) - add_dependencies( GXGeometrySystems JSONExt ) -endif() # Set up an alias with the same name that you would get by "finding" a pre-built # version of the library. diff --git a/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/MuonVolumeHandle.h b/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/MuonVolumeHandle.h index f3b2d3e1e935781bceec77823f03713f59465e45..6dfa09b676e11daac9633cf647dd6ce34aa1e19a 100644 --- a/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/MuonVolumeHandle.h +++ b/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/MuonVolumeHandle.h @@ -22,9 +22,9 @@ class MuonVolumeHandle : public VolumeHandle { public: - MuonVolumeHandle(VolumeHandleSharedData * shared,VolumeHandle * parent, const GeoPVConstLink& pv,int childNumber, + MuonVolumeHandle(VolumeHandleSharedData * shared,VolumeHandle * parent, const PVConstLink& pv,int childNumber, const MuonChamberState& mcs, const SbMatrix& accumTrans,const MuonGM::MuonStation * station, - const QList<const std::map<GeoPVConstLink, float>*>& t0s ) + const QList<const std::map<PVConstLink, float>*>& t0s ) : VolumeHandle(shared, parent, pv, childNumber, mcs, accumTrans), m_station(station), m_chamberT0s(t0s) {} @@ -41,17 +41,17 @@ public: virtual QString muonChamberT0(unsigned int i) const { if (static_cast<int>(i)>=m_chamberT0s.size()) return "ERROR bad T0 source"; - const std::map<GeoPVConstLink, float>* t0map = m_chamberT0s.at(i); + const std::map<PVConstLink, float>* t0map = m_chamberT0s.at(i); const QString no_info("?"); if (!t0map) return no_info; - const std::map<GeoPVConstLink, float>::const_iterator it = t0map->find(geoPVConstLink()); + const std::map<PVConstLink, float>::const_iterator it = t0map->find(geoPVConstLink()); return it==t0map->end() ? no_info : QString::number(it->second); } private: const MuonGM::MuonStation * m_station; - const QList<const std::map<GeoPVConstLink, float>*>& m_chamberT0s; + const QList<const std::map<PVConstLink, float>*>& m_chamberT0s; }; #endif diff --git a/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/VolumeHandle.h b/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/VolumeHandle.h index 082bb56b25041a356eeed17e40194048e22b3813..f21666c222b015f96787e75adceaed78229a53df 100644 --- a/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/VolumeHandle.h +++ b/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/VolumeHandle.h @@ -8,7 +8,7 @@ #include <vector> #include "VP1GeometrySystems/VP1GeoFlags.h" -#include "GeoModelKernel/GeoPVConstLink.h" +#include "GeoModelKernel/GeoVPhysVol.h" #include <QString> //Only initialises child classes on demand. And even then their SoNodes are not initialised until they must be shown. @@ -23,7 +23,7 @@ class VolumeHandle { public: - VolumeHandle(VolumeHandleSharedData * ,VolumeHandle * parent, const GeoPVConstLink&,int childNumber, + VolumeHandle(VolumeHandleSharedData * ,VolumeHandle * parent, const PVConstLink&,int childNumber, const SbMatrix& accumTrans = SbMatrix() ); virtual ~VolumeHandle();//lots of stuff to do here! @@ -39,7 +39,7 @@ public: int copyNumber() const;//Returns -1 if doesnt have a valid copy number (because volume is not replicated), -2 in case of error. quint32 hashID() const;//For vp1 persistification - GeoPVConstLink geoPVConstLink() const; + PVConstLink geoPVConstLink() const; const GeoMaterial * geoMaterial() const; std::string getNameStdString() const; diff --git a/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/VolumeHandleSharedData.h b/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/VolumeHandleSharedData.h index f261dbc0fe16122192fd26a701c985913a0e4d99..1ca256c3953fdb6b265bf36b7c2f6021df584343 100644 --- a/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/VolumeHandleSharedData.h +++ b/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/VolumeHandleSharedData.h @@ -8,7 +8,7 @@ //This reference counted class keeps data (and related methods) which are common //for all volume handle nodes under a given top-level handle. -#include "GeoModelKernel/GeoPVConstLink.h" +#include "GeoModelKernel/GeoVPhysVol.h" #include "VP1GeometrySystems/VP1GeoFlags.h" #include <map> class SoNode; @@ -26,7 +26,7 @@ class GeoSysController; class VolumeHandleSharedData { public: VolumeHandleSharedData(GeoSysController * controller,VP1GeoFlags::SubSystemFlag,std::map<SoSeparator*,VolumeHandle*>* sonodesep2volhandle, - const GeoPVConstLink& motherpV,PhiSectorManager*, + const PVConstLink& motherpV,PhiSectorManager*, SoMaterial * topMaterial,MatVisAttributes *,VolVisAttributes *, ZappedVolumeListModel *, VP1GeoTreeView *, SoSeparator*); ~VolumeHandleSharedData(); @@ -34,7 +34,7 @@ public: void unref(); //Fixme: Inline? - GeoPVConstLink geoPVConstLinkOfTreeTopsMother() const; + PVConstLink geoPVConstLinkOfTreeTopsMother() const; PhiSectorManager* phiSectorManager() const; VP1GeoFlags::SubSystemFlag subSystemFlag() const; SoMaterial * fallBackTopLevelMaterial() const; @@ -46,7 +46,7 @@ public: void addZappedVolumeToGui(VolumeHandle*); void removeZappedVolumesFromGui(VolumeHandle*); - SoNode * toShapeNode(const GeoPVConstLink& pV, bool *shapeIsKnown=nullptr);//Returns shape of pV->getLogVol() (uses shared instancing as appropriate) + SoNode * toShapeNode(const PVConstLink& pV, bool *shapeIsKnown=nullptr);//Returns shape of pV->getLogVol() (uses shared instancing as appropriate) SoNode * getSoCylinderOrientedLikeGeoTube(const double& radius, const double& halfLength);//(uses shared instancing as appropriate) void registerNodeSepForVolumeHandle(SoSeparator*,VolumeHandle*); diff --git a/GeoModelVisualization/VP1GeometrySystems/src/VP1GeometrySystem.cxx b/GeoModelVisualization/VP1GeometrySystems/src/VP1GeometrySystem.cxx index 3e97ae23600afe0426ec99427236e4f6ce62a528..c78289deb5a3738276165b4db703785260c5f80a 100644 --- a/GeoModelVisualization/VP1GeometrySystems/src/VP1GeometrySystem.cxx +++ b/GeoModelVisualization/VP1GeometrySystems/src/VP1GeometrySystem.cxx @@ -65,7 +65,7 @@ #include "GeoModelKernel/GeoPrintGraphAction.h" #include "GeoModelKernel/GeoMaterial.h" #include "GeoModelKernel/GeoElement.h" -#include "GeoModelKernel/GeoPVLink.h" +#include "GeoModelKernel/GeoVPhysVol.h" #include "GeoModelKernel/GeoBox.h" #include "GeoModelKernel/GeoCountVolAction.h" #include "GeoModelKernel/GeoAccessVolumeAction.h" @@ -125,11 +125,11 @@ public: SoSeparator * sceneroot; std::map<SoSeparator*,VolumeHandle*> sonodesep2volhandle; - //Might be needed later: std::map<GeoPVConstLink,VolumeHandle*> pv2volhandle; + //Might be needed later: std::map<PVConstLink,VolumeHandle*> pv2volhandle; - GeoPhysVol* getGeometry(); - GeoPhysVol* createTheWorld(GeoPhysVol* world = nullptr); - GeoPhysVol* getGeometryFromLocalDB(); + GeoVPhysVol* getGeometry(); + GeoVPhysVol* createTheWorld(const GeoVPhysVol* world = nullptr); + GeoVPhysVol* getGeometryFromLocalDB(); SoTexture2* getDummyTexture(); SoMaterial* getDummyMaterial(); @@ -496,13 +496,13 @@ void VP1GeometrySystem::buildPermanentSceneGraph(StoreGateSvc*/*detstore*/, SoSe } //_____________________________________________________________________________________ -GeoPhysVol* VP1GeometrySystem::Imp::getGeometry() +GeoVPhysVol* VP1GeometrySystem::Imp::getGeometry() { return getGeometryFromLocalDB(); // for production } //_____________________________________________________________________________________ -GeoPhysVol* VP1GeometrySystem::Imp::createTheWorld(GeoPhysVol* world) +GeoVPhysVol* VP1GeometrySystem::Imp::createTheWorld(const GeoVPhysVol* world) { if (world == nullptr) { @@ -513,7 +513,7 @@ GeoPhysVol* VP1GeometrySystem::Imp::createTheWorld(GeoPhysVol* world) const GeoLogVol* worldLog = new GeoLogVol("WorldLog", worldBox, worldMat); world = new GeoPhysVol(worldLog); } - return world; + return const_cast<GeoVPhysVol*>(world); } @@ -529,7 +529,7 @@ QString VP1GeometrySystem::Imp::selectGeometryFile() { } //_____________________________________________________________________________________ -GeoPhysVol* VP1GeometrySystem::Imp::getGeometryFromLocalDB() +GeoVPhysVol* VP1GeometrySystem::Imp::getGeometryFromLocalDB() { QString path; @@ -554,7 +554,7 @@ GeoPhysVol* VP1GeometrySystem::Imp::getGeometryFromLocalDB() if (path=="") return nullptr; - GeoPhysVol *world=getenv("GX_GEOMETRY_FILE1") ? createTheWorld(nullptr) : nullptr; + GeoVPhysVol *world=getenv("GX_GEOMETRY_FILE1") ? createTheWorld(nullptr) : nullptr; int g=0; while (path!="") { @@ -572,7 +572,7 @@ GeoPhysVol* VP1GeometrySystem::Imp::getGeometryFromLocalDB() GeoModelIO::ReadGeoModel readInGeo = GeoModelIO::ReadGeoModel(db); /* build the GeoModel geometry */ - GeoPhysVol* dbPhys = readInGeo.buildGeoModel(); // builds the whole GeoModel tree in memory + const GeoVPhysVol* dbPhys = readInGeo.buildGeoModel(); // builds the whole GeoModel tree in memory if (world) { @@ -1126,11 +1126,17 @@ double VP1GeometrySystem::Imp::inclusiveMass(const PVConstLink& pv) { GeoVolumeCursor av(pv); while (!av.atEnd()) { - mass += inclusiveMass(av.getVolume()); - mass -= volume(av.getVolume())*density; + std::string materialName=av.getVolume()->getLogVol()->getMaterial()->getName(); + + if (QString(materialName.c_str()).endsWith("Ether") || QString(materialName.c_str()).endsWith("HyperUranium")) { + // Do nothing. These are not real volumes. + } + else { + double delta = inclusiveMass(av.getVolume()) - (volume(av.getVolume())*density); + mass += delta; + } av.next(); } - return mass; } diff --git a/GeoModelVisualization/VP1GeometrySystems/src/VolumeHandle.cxx b/GeoModelVisualization/VP1GeometrySystems/src/VolumeHandle.cxx index d40b20423f1811b54863f60bdcc89b6f6a995183..804eede1d8bfb26f859b79a8b0f86ad50a5b51f0 100644 --- a/GeoModelVisualization/VP1GeometrySystems/src/VolumeHandle.cxx +++ b/GeoModelVisualization/VP1GeometrySystems/src/VolumeHandle.cxx @@ -43,11 +43,11 @@ //____________________________________________________________________ class VolumeHandle::Imp { public: - Imp(VolumeHandleSharedData * the_cd, const GeoPVConstLink& the_pV, const SbMatrix& the_ac) + Imp(VolumeHandleSharedData * the_cd, const PVConstLink& the_pV, const SbMatrix& the_ac) : commondata(the_cd), pV(the_pV),accumTrans(the_ac),attachsepHelper(0),attachlabelSepHelper(0),nodesep(0), material(0), label_sep(0), labels(0), isattached(false) {} VolumeHandleSharedData * commondata; - GeoPVConstLink pV; + PVConstLink pV; const SbMatrix accumTrans;//FIXME: Use pointer - and free once children are created AND nodesep has been build. Or just construct on the fly! VP1ExtraSepLayerHelper * attachsepHelper; @@ -90,7 +90,7 @@ QDataStream & operator>> ( QDataStream & in, VolumeHandle::Imp::VolState & vs ) } //____________________________________________________________________ -VolumeHandle::VolumeHandle(VolumeHandleSharedData * cd,VolumeHandle * parent, const GeoPVConstLink& pV, int childNumber, const SbMatrix& accumTrans) +VolumeHandle::VolumeHandle(VolumeHandleSharedData * cd,VolumeHandle * parent, const PVConstLink& pV, int childNumber, const SbMatrix& accumTrans) : m_d(new Imp(cd,pV,accumTrans)), m_childNumber(childNumber), m_nchildren(childNumber>=0?pV->getNChildVols():0), m_parent(parent), m_state(VP1GeoFlags::CONTRACTED) { @@ -156,7 +156,7 @@ void VolumeHandle::initialiseChildren() } //____________________________________________________________________ -GeoPVConstLink VolumeHandle::geoPVConstLink() const +PVConstLink VolumeHandle::geoPVConstLink() const { return m_d->pV; } @@ -507,7 +507,7 @@ void VolumeHandle::detachAllContractedChildren() { //____________________________________________________________________ int VolumeHandle::copyNumber() const { - GeoPVConstLink parent_pV; + PVConstLink parent_pV; if (m_parent) { parent_pV = m_parent->geoPVConstLink(); } else { diff --git a/GeoModelVisualization/VP1GeometrySystems/src/VolumeHandleSharedData.cxx b/GeoModelVisualization/VP1GeometrySystems/src/VolumeHandleSharedData.cxx index 5752a534aa768687b7b0f273cf8e433a25092d4c..0ff86e8b5382444c4e2b2d758dacb57d0e4ac2a2 100644 --- a/GeoModelVisualization/VP1GeometrySystems/src/VolumeHandleSharedData.cxx +++ b/GeoModelVisualization/VP1GeometrySystems/src/VolumeHandleSharedData.cxx @@ -28,7 +28,7 @@ public: std::map<double, SoNode *> id2shape; SoVisualizeAction visaction; std::map<SoSeparator*,VolumeHandle*>* sonodesep2volhandle; - GeoPVConstLink motherpV; + PVConstLink motherpV; PhiSectorManager* phisectormanager; VP1GeoFlags::SubSystemFlag subsysflag; SoMaterial * topMaterial; @@ -42,7 +42,7 @@ public: VolumeHandleSharedData::VolumeHandleSharedData(GeoSysController * controller, VP1GeoFlags::SubSystemFlag flag, std::map<SoSeparator*,VolumeHandle*>* sonodesep2volhandle, - const GeoPVConstLink& motherpV, PhiSectorManager*psm, + const PVConstLink& motherpV, PhiSectorManager*psm, SoMaterial * topMaterial, MatVisAttributes *matVisAttributes,VolVisAttributes *volVisAttributes, ZappedVolumeListModel * zappedvolumelistmodel, VP1GeoTreeView * volbrowser, SoSeparator* textSep ) @@ -159,7 +159,7 @@ void VolumeHandleSharedData::setShowVolumeOutlines(SoGroup*nodegroup,bool showvo } } //_____________________________________________________________________________________ -SoNode * VolumeHandleSharedData::toShapeNode(const GeoPVConstLink& pV, bool * shapeIsKnown) +SoNode * VolumeHandleSharedData::toShapeNode(const PVConstLink& pV, bool * shapeIsKnown) { const GeoLogVol * logVolume = pV->getLogVol(); @@ -182,7 +182,7 @@ SoNode * VolumeHandleSharedData::toShapeNode(const GeoPVConstLink& pV, bool * sh } shape = m_d->visaction.getShape(); if (!shape) { - GeoPVConstLink parent=pV->getParent(); + PVConstLink parent=pV->getParent(); parent->getLogVol()->getShape()->exec(&(m_d->visaction)); shape = m_d->visaction.getShape(); if (shapeIsKnown) *shapeIsKnown=false; @@ -219,7 +219,7 @@ SoNode * VolumeHandleSharedData::getSoCylinderOrientedLikeGeoTube(const double& } //____________________________________________________________________ -GeoPVConstLink VolumeHandleSharedData::geoPVConstLinkOfTreeTopsMother() const +PVConstLink VolumeHandleSharedData::geoPVConstLinkOfTreeTopsMother() const { return m_d->motherpV; } diff --git a/GeoModelVisualization/VP1GeometrySystems/src/VolumeTreeModel.cxx b/GeoModelVisualization/VP1GeometrySystems/src/VolumeTreeModel.cxx index 64a6f3e10b36e0241eae099518b6b388ddff6454..511b78df6106ff80ca3846c4f57768c0bf2fc96f 100644 --- a/GeoModelVisualization/VP1GeometrySystems/src/VolumeTreeModel.cxx +++ b/GeoModelVisualization/VP1GeometrySystems/src/VolumeTreeModel.cxx @@ -39,7 +39,7 @@ public: class SubSystem: public VolumeHandle { public: SubSystem(SectionInfo *si,VP1GeoFlags::SubSystemFlag sf) - : VolumeHandle(0,0, GeoPVConstLink(), -1), + : VolumeHandle(0,0, PVConstLink(), -1), section(si), subsysflag(sf) {} ~SubSystem() { VolumeHandle::VolumeHandleListItr volItr, volItrE(volhandlelist.end()); @@ -60,7 +60,7 @@ public: //Class for the dynamic information about sections and their daughter subsystems: class SectionInfo: public VolumeHandle { public: - SectionInfo(): VolumeHandle(0,0, GeoPVConstLink(), -2) {} + SectionInfo(): VolumeHandle(0,0, PVConstLink(), -2) {} // QList<SubSystem*> enabledSubSystems; QList<SubSystem*> disabledSubSystems; @@ -326,12 +326,12 @@ int VolumeTreeModel::rowCount(const QModelIndex& parent) const //____________________________________________________________________ QVariant VolumeTreeModel::data(const QModelIndex& index, int role) const { - if ((role!=Qt::DisplayRole&&role!=Qt::TextColorRole)||!index.isValid()) + if ((role!=Qt::DisplayRole&&role!=Qt::ForegroundRole)||!index.isValid()) return QVariant(); VolumeHandle *volumeHandle = Imp::handlePointer(index); if (Imp::isRegularVolumeHandle(volumeHandle)) { - if (role==Qt::TextColorRole) { + if (role==Qt::ForegroundRole) { if (volumeHandle->isAttached()) return QVariant(); else @@ -350,7 +350,7 @@ QVariant VolumeTreeModel::data(const QModelIndex& index, int role) const return volumeHandle->getName() + " (" + QString::fromStdString(volumeHandle->geoMaterial()->getName()) + ") ("+ volState + ")" ; } - if (role==Qt::TextColorRole) + if (role==Qt::ForegroundRole) return QVariant(); if (Imp::isSubSystemPointer(volumeHandle)) @@ -365,7 +365,7 @@ QVariant VolumeTreeModel::data(const QModelIndex& index, int role) const Qt::ItemFlags VolumeTreeModel::flags(const QModelIndex &index) const { if (!index.isValid()) - return 0; + return Qt::NoItemFlags; if (Imp::isRegularVolumeHandle(Imp::handlePointer(index))) return Qt::ItemIsEnabled | Qt::ItemIsSelectable; diff --git a/GeoModelVisualization/VP1GeometrySystems/src/settings_interactions_form.ui b/GeoModelVisualization/VP1GeometrySystems/src/settings_interactions_form.ui index 7ebd63257a292f3e7c4792101c2f59e044a80359..16ab476e81a2b8f3bcc070df28f4b14164033208 100644 --- a/GeoModelVisualization/VP1GeometrySystems/src/settings_interactions_form.ui +++ b/GeoModelVisualization/VP1GeometrySystems/src/settings_interactions_form.ui @@ -77,7 +77,7 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">In the case where either the selected volume or one its daugthers (or daughters daughters, etc.), is defined as a boolean volume, this might not give an entirely accurate result.</p></body></html></string> </property> <property name="text"> - <string>Mass (unreliable)</string> + <string>Mass (slow!)</string> </property> </widget> </item> diff --git a/GeoModelVisualization/VP1Gui/CMakeLists.txt b/GeoModelVisualization/VP1Gui/CMakeLists.txt index 6cd58de442fca559050898be14ceac172200e314..6cc53cc91b5f5cd6b66b40b36d8d9e610e442989 100644 --- a/GeoModelVisualization/VP1Gui/CMakeLists.txt +++ b/GeoModelVisualization/VP1Gui/CMakeLists.txt @@ -9,8 +9,8 @@ file( GLOB RCS src/*.qrc ) # Add the library. add_library( GXGui SHARED ${SOURCES} ${HEADERS} ${UIS} ${RCS} ) target_link_libraries( GXGui - PUBLIC Coin::Coin Qt5::Core Qt5::Gui Qt5::Widgets SoQt::SoQt GXBase - PRIVATE Qt5::PrintSupport Qt5::OpenGL ) + PUBLIC Coin::Coin Qt${QT_VERSION}::Core Qt${QT_VERSION}::Gui Qt${QT_VERSION}::Widgets SoQt::SoQt GXBase + PRIVATE Qt${QT_VERSION}::PrintSupport Qt${QT_VERSION}::OpenGL ) target_include_directories( GXGui PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> $<INSTALL_INTERFACE:include> ) diff --git a/GeoModelVisualization/VP1Gui/VP1Gui/GXExecutionScheduler.h b/GeoModelVisualization/VP1Gui/VP1Gui/GXExecutionScheduler.h index 41b9a4805f47e0cc0eb10654954bb298ca3174c4..50e789ba8d04d56f3f1b30e637e9d536483aac74 100644 --- a/GeoModelVisualization/VP1Gui/VP1Gui/GXExecutionScheduler.h +++ b/GeoModelVisualization/VP1Gui/VP1Gui/GXExecutionScheduler.h @@ -20,14 +20,16 @@ // include VP1 #include "VP1Gui/VP1QtApplication.h" +#include "VP1Base/IVP1ChannelWidget.h" // include Qt #include <QObject> #include <QStringList> - +#include <QTime> +#include <QDir> class IVP1System; -class IVP1ChannelWidget; + class GXExecutionScheduler : public QObject { diff --git a/GeoModelVisualization/VP1Gui/VP1Gui/GXMainWindow.h b/GeoModelVisualization/VP1Gui/VP1Gui/GXMainWindow.h index 8cc8b3444e8618ee602cabb15253638d1765efd3..29879847f8b4a49b15100608bac0f479119af5be 100644 --- a/GeoModelVisualization/VP1Gui/VP1Gui/GXMainWindow.h +++ b/GeoModelVisualization/VP1Gui/VP1Gui/GXMainWindow.h @@ -19,7 +19,6 @@ #include "ui_gxmainwindow.h" // include VP1 -#include "VP1Gui/VP1EventDisplayEditor.h" // include Qt #include <QQueue> @@ -28,7 +27,6 @@ class VP1ChannelManager; class VP1TabManager; -class QStringList; class IVP1ChannelWidget; class GXExecutionScheduler; class VP1PluginDialog; @@ -179,8 +177,6 @@ protected: QMutex* m_mutex; - // Event display editor - VP1EventDisplayEditor* m_edEditor; }; diff --git a/GeoModelVisualization/VP1Gui/VP1Gui/VP1EventDisplayEditor.h b/GeoModelVisualization/VP1Gui/VP1Gui/VP1EventDisplayEditor.h deleted file mode 100644 index 9328c3c6f859043bc18e56a63b413b95cd97253d..0000000000000000000000000000000000000000 --- a/GeoModelVisualization/VP1Gui/VP1Gui/VP1EventDisplayEditor.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -*/ - - -//////////////////////////////////////////////////////////////// -// // -// Header file for class VP1EventDisplayEditor // -// // -// Description: Event display editor. // -// // -// Author: Riccardo-Maria BIANCHI (rbianchi@cern.ch) // -// Initial version: September 2013 // -// // -//////////////////////////////////////////////////////////////// - -#ifndef VP1CUSTOMTOUREDITOR_H -#define VP1CUSTOMTOUREDITOR_H - -#include "VP1Gui/VP1EventDisplaySceneView.h" - -#include "VP1Base/IVP1ChannelWidget.h" -#include "VP1Base/VP1Msg.h" - -#include <QWidget> -#include <QGraphicsView> -#include <QGraphicsScene> -#include <QGraphicsPixmapItem> -#include <QSplitter> - -class GXMainWindow; - - -class VP1EventDisplayEditor : public QWidget { - - Q_OBJECT - -public: - - VP1EventDisplayEditor(GXMainWindow* mainWindow, QList<unsigned long long> listRunEventNumberTimestamp); - virtual ~VP1EventDisplayEditor(); - -// QGraphicsView* getView(); - - void addPixmapList(QList<QPixmap>& list, QStringList& listNames); - void setTabsList(QStringList listNames); - - // void setState(QByteArray); - // QByteArray state() const; - - -protected: - void closeEvent(QCloseEvent*); - -private slots: - // void buttonClicked(); - void setTextLabel(); - void removeObject(); - void addLogo(); - void setBackgroundColor(); - void savePicture(); - void printPicture(); - void getTabSnapshot(); - void enableCustomTextField(bool checked); - -private: - - QString getEventDetailsLabel(); - void addTextLabel(QString text, QFont font); - - class Imp; - Imp * m_d; - QGraphicsScene* m_scene; -// QGraphicsScene* scene_preview; - QList< QGraphicsItem* > m_sceneItems; -// QGraphicsItem *itemPreview; - - VP1EventDisplaySceneView* m_preview; - - QStringList m_listTabNames; - QList<IVP1ChannelWidget*> m_allTabs; - - GXMainWindow* m_mainWindow; - - int m_runNumber; - unsigned long long m_eventNumber; - unsigned m_eventTimestamp; - -// QSplitter *h1Splitter; -// QSplitter *h2Splitter; -}; - -#endif diff --git a/GeoModelVisualization/VP1Gui/VP1Gui/VP1EventDisplaySceneView.h b/GeoModelVisualization/VP1Gui/VP1Gui/VP1EventDisplaySceneView.h deleted file mode 100644 index 37825e4a9addb78da0deaa79af60f8746cbdaf1d..0000000000000000000000000000000000000000 --- a/GeoModelVisualization/VP1Gui/VP1Gui/VP1EventDisplaySceneView.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -*/ - -/* - * jira_1 - * VP1EventDisplaySceneView.h - * - * Created on: Sep 26, 2013 - * Author: rbianchi <Riccardo.Maria.Bianchi@cern.ch> - * - */ - -#ifndef VP1EVENTDISPLAYSCENEVIEW_H_ -#define VP1EVENTDISPLAYSCENEVIEW_H_ - - -#include <QtGui> -#include <QFrame> -#include <QHBoxLayout> -#include <QVBoxLayout> -#include <QGraphicsView> - -QT_FORWARD_DECLARE_CLASS(QLabel) -QT_FORWARD_DECLARE_CLASS(QSlider) -QT_FORWARD_DECLARE_CLASS(QToolButton) - -class VP1EventDisplaySceneView; - - -/* - * we create a new class inheriting from QGraphicsView, - * to reimplement the wheel event in order to use the wheel - * to zoom the image, when used over the zoom sliders - */ -class GraphicsView : public QGraphicsView -{ - Q_OBJECT -public: - GraphicsView(VP1EventDisplaySceneView *v) : QGraphicsView(), m_view(v) { } - -protected: - void wheelEvent(QWheelEvent *); - -private: - VP1EventDisplaySceneView *m_view; -}; - - - -/* - * The QFrame which contains the graphicsView and all other widgets. - * - * If the 'preview' argument is set to true, then a 'preview' view is built - * without rotation sliders and the zoom set to see the whole scene. - */ -class VP1EventDisplaySceneView : public QFrame -{ - Q_OBJECT -public: - VP1EventDisplaySceneView(const QString &name, bool preview = false, QWidget *parent = 0); - ~VP1EventDisplaySceneView(); - - QGraphicsView *view() const; - void setPreviewZoom(qreal xx); - void addRenderingFrame(); - void showRenderingFrame(); - void hideRenderingFrame(); - - public slots: - void zoomIn(int level = 1); - void zoomOut(int level = 1); - void print(); - - private slots: - void resetView(); - void setResetButtonEnabled(); - void setupMatrix(); - void togglePointerMode(); - void toggleOpenGL(); - void toggleAntialiasing(); - void rotateLeft(); - void rotateRight(); - - private: - GraphicsView *m_graphicsView; - - bool m_preview; - - QGraphicsRectItem* m_frame; - QGraphicsLineItem * m_line; - - QLabel *m_label; - QLabel *m_label2; - - QToolButton *m_selectModeButton; - QToolButton *m_dragModeButton; - QToolButton *m_openGlButton; - QToolButton *m_antialiasButton; - QToolButton *m_printButton; - QToolButton *m_resetButton; - - QVBoxLayout *m_zoomSliderLayout; - QSlider *m_zoomSlider; - QToolButton *m_zoomInIcon; - QToolButton *m_zoomOutIcon; - - QHBoxLayout *m_rotateSliderLayout; - QSlider *m_rotateSlider; - QToolButton *m_rotateLeftIcon; - QToolButton *m_rotateRightIcon; - -}; - - -#endif /* VP1EVENTDISPLAYSCENEVIEW_H_ */ diff --git a/GeoModelVisualization/VP1Gui/VP1Gui/VP1TabManager.h b/GeoModelVisualization/VP1Gui/VP1Gui/VP1TabManager.h index 8f21ea43185c1561a162776f32188d58ff264449..98b2e0198ce18a03491a5502fba5b39c19522f9c 100644 --- a/GeoModelVisualization/VP1Gui/VP1Gui/VP1TabManager.h +++ b/GeoModelVisualization/VP1Gui/VP1Gui/VP1TabManager.h @@ -71,10 +71,11 @@ public slots: void cloneTab(QString oldtabname,QString newtabname); void removeAllTabs(); - +#ifdef SAVEANDRESTORE void saveConfigurationToFile(QString filename,const bool& askonoverride=true); void loadConfigurationFromFile(QString filename,const QMap<QString,QString>& availableplugins); - +#endif + void showChannelFullScreen(IVP1ChannelWidget*); void showCurrentChannelFullScreen(); void showTabFullScreen(QString tabname); @@ -101,9 +102,11 @@ protected: bool eventFilter ( QObject *, QEvent * ); typedef QPair<QByteArray,QMultiMap<QString,QByteArray> > ChanState; +#ifdef SAVEANDRESTORE void serializeChannelState(IVP1ChannelWidget*,ChanState&state); void unserializeChannelState(IVP1ChannelWidget*cw,ChanState tate); - +#endif + protected slots: void currentVisibleChanged(); void executePendingChannelRemoval(); diff --git a/GeoModelVisualization/VP1Gui/src/GXExecutionScheduler.cxx b/GeoModelVisualization/VP1Gui/src/GXExecutionScheduler.cxx index e637803b6dbb3824e1e3f976517a24c3c978da38..20d3664d4ac8566331678035f37a88a43b8bcf35 100644 --- a/GeoModelVisualization/VP1Gui/src/GXExecutionScheduler.cxx +++ b/GeoModelVisualization/VP1Gui/src/GXExecutionScheduler.cxx @@ -51,7 +51,7 @@ #include <QApplication> #include <QProgressBar> -#include <QDesktopWidget> +//#include <QDesktopWidget> #include <QMouseEvent> #include <QWheelEvent> #include <QCursor> @@ -60,7 +60,7 @@ #include <QStringList> #include <QMessageBox> #include <QCommandLineParser> - +#include <QDebug> #include <Inventor/C/errors/debugerror.h> #include <Inventor/Qt/SoQt.h> @@ -222,7 +222,7 @@ public: */ qDebug() << "key pressed (code):" << keyEvent->key() << "key pressed (text):" << keyEvent->text(); if (keyEvent->text() != "") txt = txt + "+" + keyEvent->text(); - else txt = txt + "+" + keyEvent->key(); + else txt = txt + "+" + (char) keyEvent->key(); } // std::cout<<"Popup (dt="<<timediff<<") "<<txt.toStdString()<<". watched = "<<watched @@ -611,7 +611,6 @@ bool GXExecutionScheduler::isRefreshing() const { return m_d->currentsystemrefreshing; } - //___________________________________________________________________ void GXExecutionScheduler::refreshSystem(IVP1System*s) { @@ -888,8 +887,8 @@ void GXExecutionScheduler::actualUncreateAndDelete(IVP1ChannelWidget*cw) //___________________________________________________________________ void GXExecutionScheduler::Imp::warnIfWidgetsAlive() { - QSet<QWidget*> w_ignore, wl = QApplication::allWidgets().toSet(); - w_ignore<<qApp->desktop(); + QSet<QWidget*> w_ignore, wl(QApplication::allWidgets().begin(), QApplication::allWidgets().end());// = QApplication::allWidgets().toSet(); + //w_ignore<<qApp->desktop(); foreach (QObject*o,qApp->children()) { if (o->isWidgetType()) w_ignore << static_cast<QWidget*>(o); diff --git a/GeoModelVisualization/VP1Gui/src/GXMainWindow.cxx b/GeoModelVisualization/VP1Gui/src/GXMainWindow.cxx index 56b758c2edd7c465288767024d5f5e782f328c5c..78ac78f3479f87ee18f9b4cefc04d2cc87bb33d7 100644 --- a/GeoModelVisualization/VP1Gui/src/GXMainWindow.cxx +++ b/GeoModelVisualization/VP1Gui/src/GXMainWindow.cxx @@ -81,11 +81,9 @@ GXMainWindow::GXMainWindow(GXExecutionScheduler*sched,QWidget * parent) m_scheduler(sched), m_settingsfile(QDir::homePath()+QDir::separator()+".atlasvp1"), m_userRequestedExit(false), - m_mutex(new QMutex()), - m_edEditor(0) + m_mutex(new QMutex()) { setupUi(this); // this sets up the GUI - setupStatusBar(); // @@ -258,6 +256,7 @@ GXMainWindow::GXMainWindow(GXExecutionScheduler*sched,QWidget * parent) menuConfiguration->setVisible(false); menuConfiguration->setEnabled(false); menuConfiguration->setTitle(""); + } //_________________________________________________________________________________ @@ -346,10 +345,6 @@ void GXMainWindow::setupStatusBar() { //_________________________________________________________________________________ GXMainWindow::~GXMainWindow() { - if (m_edEditor) { - VP1Msg::messageDebug("deleting the editor"); - delete m_edEditor; - } VP1Msg::messageDebug("deleting the tab manager"); delete m_tabmanager; VP1Msg::messageDebug("deleting the channel manager"); @@ -463,7 +458,7 @@ void GXMainWindow::request_saveasConfig() { if (!filename.endsWith(".vp1")) filename += ".vp1"; - m_tabmanager->saveConfigurationToFile(filename,false/*Since the filedialog already asks*/); + //m_tabmanager->saveConfigurationToFile(filename,false/*Since the filedialog already asks*/); m_currentconfigfile=filename; } @@ -474,7 +469,7 @@ void GXMainWindow::request_saveConfig() request_saveasConfig(); return; } - m_tabmanager->saveConfigurationToFile(m_currentconfigfile,false); + //m_tabmanager->saveConfigurationToFile(m_currentconfigfile,false); } //_________________________________________________________________________________ @@ -485,7 +480,7 @@ void GXMainWindow::request_loadConfig() "VP1 configuration files (*.vp1)",0,QFileDialog::DontResolveSymlinks); if(filename.isEmpty()) return; - m_tabmanager->loadConfigurationFromFile(filename,availablePluginFiles()); + //m_tabmanager->loadConfigurationFromFile(filename,availablePluginFiles()); m_currentconfigfile=filename; } @@ -525,7 +520,7 @@ QMap<QString,QString> GXMainWindow::availableFiles(const QString& extension, //Add directories from extradirenvvar (e.g. $GXPLUGINPATH) qDebug() << "GXPLUGINPATH: " << QString(::getenv(extradirenvvar.toStdString().c_str())); - QStringList vp1pluginpath = extradirenvvar.isEmpty() ? QStringList() : QString(::getenv(extradirenvvar.toStdString().c_str())).split(":",QString::SkipEmptyParts); + QStringList vp1pluginpath = extradirenvvar.isEmpty() ? QStringList() : QString(::getenv(extradirenvvar.toStdString().c_str())).split(":",Qt::SkipEmptyParts); if(VP1Msg::debug()){ qDebug() << "extradirenvvar:" << extradirenvvar; qDebug() << "vp1pluginpath A :" << vp1pluginpath; @@ -554,7 +549,7 @@ QMap<QString,QString> GXMainWindow::availableFiles(const QString& extension, QString path = QString(::getenv(pathvar.toStdString().c_str())); if (!path.isEmpty()) { //!instareasubdir.isEmpty()&& - QStringList tmp = path.split(":",QString::SkipEmptyParts);//This 'tmp' is for SLC3 compilation. + QStringList tmp = path.split(":",Qt::SkipEmptyParts);//This 'tmp' is for SLC3 compilation. foreach (QString dir,tmp) { vp1pluginpath << ( instareasubdir.isEmpty() ? dir : dir+QDir::separator()+QDir::separator()+instareasubdir ); } @@ -766,16 +761,6 @@ void GXMainWindow::makeAllChannelsEventDisplay() getAllChannelsIntoSnapshots(list, listNames); - // create a new editor window - m_edEditor = new VP1EventDisplayEditor(this, listRunEventNumberTimestamp); - - m_edEditor->addPixmapList(list, listNames); - - // pass the lists of all tabs and their names to the editor - m_edEditor->setTabsList( listNames); - - m_edEditor->show(); - } @@ -1085,7 +1070,7 @@ void GXMainWindow::request_printChannel() { //_________________________________________________________________________________ void GXMainWindow::loadConfigurationFromFile(QString file) { - m_tabmanager->loadConfigurationFromFile(file,availablePluginFiles()); + //m_tabmanager->loadConfigurationFromFile(file,availablePluginFiles()); } //_________________________________________________________________________________ @@ -1093,7 +1078,7 @@ void GXMainWindow::replaceConfigurationFile(QString file) { VP1Msg::messageDebug("GXMainWindow::replaceConfigurationFile() : " + file); m_tabmanager->removeAllTabs(); - m_tabmanager->loadConfigurationFromFile(file,availablePluginFiles()); + // m_tabmanager->loadConfigurationFromFile(file,availablePluginFiles()); } diff --git a/GeoModelVisualization/VP1Gui/src/VP1ChannelManager.cxx b/GeoModelVisualization/VP1Gui/src/VP1ChannelManager.cxx index 6502f1d17237a267dff7ef9ef026e0aa99299c58..1d487d7ef4b0bf1e2e9a33cdc3e0f057f36bb6d2 100644 --- a/GeoModelVisualization/VP1Gui/src/VP1ChannelManager.cxx +++ b/GeoModelVisualization/VP1Gui/src/VP1ChannelManager.cxx @@ -63,7 +63,7 @@ #include <QFileInfo> #include <QMap> #include <QScrollArea> - +#include <QLibraryInfo> #include <map> #include <set> #include <cassert> diff --git a/GeoModelVisualization/VP1Gui/src/VP1DockWidget.cxx b/GeoModelVisualization/VP1Gui/src/VP1DockWidget.cxx index d2a36b219f0ce38465c948c9830cef0b97d6c99b..2261983eee32241591f0b3ee4d5355903d9e3669 100644 --- a/GeoModelVisualization/VP1Gui/src/VP1DockWidget.cxx +++ b/GeoModelVisualization/VP1Gui/src/VP1DockWidget.cxx @@ -144,9 +144,9 @@ VP1DockWidget::VP1DockWidget ( IVP1ChannelWidget * cw, VP1TabManager* tm ) //Figure out what margin our drawn frame imposes: setSelected(); int marg_left, marg_top, marg_right, marg_bottom; - m_d->frame->getContentsMargins ( &marg_left, &marg_top, &marg_right, &marg_bottom ); - Q_ASSERT(marg_left==marg_top&&marg_left==marg_right&&marg_left==marg_bottom&&"Qt changed its margin behaviour for QFrame!!"); - m_d->unselectedmargin=marg_left; + QMargins margins=m_d->frame->contentsMargins (); + Q_ASSERT(margins.left()==margins.top() &&margins.left()==margins.right()&&margins.left()==margins.bottom() &&"Qt changed its margin behaviour for QFrame!!"); + m_d->unselectedmargin=margins.left(); //Channel starts unselected: setUnselected(); @@ -226,7 +226,7 @@ void VP1DockWidget::setSelected() m_d->selected=true; m_d->frame->setStyleSheet(m_d->selectedstylesheet); assert(m_d->vboxLayout); - m_d->vboxLayout->setMargin(0); + // m_d->vboxLayout->setMargin(0); m_d->frame->setFrameShape(QFrame::StyledPanel); updateTitle(); } @@ -239,7 +239,7 @@ void VP1DockWidget::setUnselected() m_d->selected=false; m_d->frame->setStyleSheet(""); assert(m_d->vboxLayout); - m_d->vboxLayout->setMargin(m_d->unselectedmargin); + // m_d->vboxLayout->setMargin(m_d->unselectedmargin); m_d->frame->setFrameShape(QFrame::NoFrame); updateTitle(); } diff --git a/GeoModelVisualization/VP1Gui/src/VP1EventDisplayEditor.cxx b/GeoModelVisualization/VP1Gui/src/VP1EventDisplayEditor.cxx deleted file mode 100644 index 78325dd50a9e276971e33c5eaeb52764a4adf705..0000000000000000000000000000000000000000 --- a/GeoModelVisualization/VP1Gui/src/VP1EventDisplayEditor.cxx +++ /dev/null @@ -1,730 +0,0 @@ -/* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -*/ - - -//////////////////////////////////////////////////////////////// -// // -// Header file for class VP1EventDisplayEditor // -// // -// Description: Event display editor. // -// // -// Author: Riccardo-Maria BIANCHI (rbianchi@cern.ch) // -// Initial version: September 2013 // -// // -//////////////////////////////////////////////////////////////// - -#include "VP1Gui/VP1EventDisplayEditor.h" -#include "ui_vp1eventdisplayeditor.h" - -#include "VP1Base/VP1ExaminerViewer.h" -#include "VP1Base/VP1QtInventorUtils.h" -#include "VP1Base/VP1Serialise.h" -#include "VP1Base/VP1Deserialise.h" -#include "VP1Gui/GXMainWindow.h" - -#include <QRectF> -#include <QShortcut> -#include <QCloseEvent> -#include <QFileDialog> - -#include <iostream> - - -//____________________________________________________________________ -class VP1EventDisplayEditor::Imp { - -public: - - VP1EventDisplayEditor * theclass; - Ui::VP1EventDisplayEditorForm ui; - - // VP1ExaminerViewer* viewer; - - // QGraphicsScene* scene; - - // QWidget * frameHolderWidget; - -}; - - -////____________________________________________________________________ -//QByteArray VP1EventDisplayEditor::state() const -//{ -// VP1Serialise s(0/*version*/); -// QList<QByteArray> frameStates; -// foreach(VP1CustomTourFrameWidget*frame,d->frames) { -// frameStates << frame->serialise(); -// s.ignoreWidget(frame); -// } -// s.save(frameStates); -// s.save(d->ui.doubleSpinBox_theta); -// s.save(d->ui.doubleSpinBox_radius); -// s.save(d->ui.groupBox_utilityZoom); -// s.warnUnsaved(this); -// return s.result(); -//} - -////____________________________________________________________________ -//void VP1EventDisplayEditor::setState(QByteArray ba) -//{ -// foreach(VP1CustomTourFrameWidget*frame,d->frames) -// frame->deleteLater(); -// d->frames.clear(); -// -// VP1Deserialise s(ba); -// if (s.version()!=0) -// return; -// QList<QByteArray> frameStates = s.restore<QList<QByteArray> >(); -// s.restore(d->ui.doubleSpinBox_theta); -// s.restore(d->ui.doubleSpinBox_radius); -// s.restore(d->ui.groupBox_utilityZoom); -// s.warnUnrestored(this); -// -// d->ui.widget_utilityZoomContents->setVisible(d->ui.groupBox_utilityZoom->isChecked()); -// -// foreach(QByteArray ba2, frameStates) -// d->addFrame(new VP1CustomTourFrameWidget(ba2)); -// d->updateFrameListVisuals(); -// enabledFrameListChanged(); -//} - - -/* - * My first, old version - */ -////____________________________________________________________________ -////VP1EventDisplayEditor::VP1EventDisplayEditor(VP1ExaminerViewer* viewer) -//VP1EventDisplayEditor::VP1EventDisplayEditor() -//: QWidget(0,Qt::WindowStaysOnTopHint), d(new Imp) -//{ -// d->theclass = this; -// d->ui.setupUi(this); -// -// scene = new QGraphicsScene(); // the size of the scene is by default infinite. But we will limit the view, here below -// scene->setSceneRect(QRectF(0.0, 0.0, 4000., 2641.)); -// -// scene_preview = new QGraphicsScene(); -// -// -// d->ui.graphicsView->setScene(scene); -// d->ui.graphicsView->setSceneRect(0, 0, 4000, 2641); // the size of a final ATLAS event display -// d->ui.graphicsView->setMaximumSize(1000, 660); // the size of the view window on the screen -// -// d->ui.graphicsView_preview->setScene(scene_preview); -// d->ui.graphicsView_preview->setSceneRect(0, 0, 333, 220); // the size of the preview scene -// d->ui.graphicsView_preview->setMaximumSize(333, 220); // the size of the preview window -// -// // set the default bkg color: black -// setBackgroundColor(); -// -// setWindowIcon(QIcon(QString(":/vp1/icons/icons/3d_32x32.png"))); -// -// connect(d->ui.pushButton_addText,SIGNAL(clicked()), this,SLOT(addTextLabel())); -// connect(d->ui.pushButton_removeObj,SIGNAL(clicked()), this,SLOT(removeObject())); -// connect(d->ui.pushButton_addLogo,SIGNAL(clicked()), this,SLOT(addLogo())); -// -// connect(d->ui.radioButton_black,SIGNAL(clicked()), this,SLOT(setBackgroundColor())); -// connect(d->ui.radioButton_white,SIGNAL(clicked()), this,SLOT(setBackgroundColor())); -// connect(d->ui.radioButton_transparent,SIGNAL(clicked()), this,SLOT(setBackgroundColor())); -// -// connect(scene,SIGNAL(changed(const QList<QRectF>&)), this,SLOT(updatePreview(const QList<QRectF>&))); -// -//} - - -/* - * new version - */ -//____________________________________________________________________ -VP1EventDisplayEditor::VP1EventDisplayEditor(GXMainWindow* mainWindow, QList<unsigned long long> listRunEventNumberTimestamp) -//: QWidget(0,Qt::WindowStaysOnTopHint), d(new Imp) -: QWidget(0), m_d(new Imp) -{ - m_mainWindow = mainWindow; - - m_runNumber = listRunEventNumberTimestamp.size()>0 ? listRunEventNumberTimestamp[0]:0; - m_eventNumber = listRunEventNumberTimestamp.size()>1 ? listRunEventNumberTimestamp[1]:0; - m_eventTimestamp = listRunEventNumberTimestamp.size()>2 ? listRunEventNumberTimestamp[2]:0; - - - m_d->theclass = this; - m_d->ui.setupUi(this); - - /* initialize the scene - * - * this is the scene that will be rendered and saved to the file. - * By default the scene dimension is 4000x2641 pixels. - * - */ - m_scene = new QGraphicsScene(); - m_scene->setSceneRect(QRectF(0.0, 0.0, 4000., 2641.)); - - - VP1EventDisplaySceneView *view = new VP1EventDisplaySceneView("Full-size view"); - view->view()->setScene(m_scene); - - m_preview = new VP1EventDisplaySceneView("Preview", true); - m_preview->view()->setScene(m_scene); - - // the right splitter, containing the list of objects in the scene and the preview - QSplitter *previewSplitter = new QSplitter; - previewSplitter->setOrientation(Qt::Vertical); - - // the center splitter, containing the main view and the preview splitter - QSplitter *viewSplitter = new QSplitter; - viewSplitter->setOrientation(Qt::Horizontal); - - // the center splitter, containing the main view and the preview splitter - QSplitter *toolsSplitter = new QSplitter; - toolsSplitter->setOrientation(Qt::Vertical); - - // the main splitter, containing all views - QSplitter *mainSplitter = new QSplitter; - mainSplitter->setOrientation(Qt::Horizontal); - - - previewSplitter->addWidget(m_d->ui.groupBox_objectList); - previewSplitter->addWidget(m_preview); - previewSplitter->addWidget(m_d->ui.groupBox_actions); - - - QWidget *containerPreview = new QWidget; - QVBoxLayout *containerPreview_layout = new QVBoxLayout; - - containerPreview_layout->addWidget(previewSplitter); - containerPreview->setLayout(containerPreview_layout); - - viewSplitter->addWidget(view); - viewSplitter->addWidget(containerPreview); - - QWidget *containerAllViews = new QWidget; - QHBoxLayout *containerAllViews_layout = new QHBoxLayout; - containerAllViews_layout->addWidget(viewSplitter); - containerAllViews->setLayout(containerAllViews_layout); - - - toolsSplitter->addWidget(m_d->ui.groupBox_getTab); - toolsSplitter->addWidget(m_d->ui.groupBox_bkg); - toolsSplitter->addWidget(m_d->ui.groupBox_logo); - toolsSplitter->addWidget(m_d->ui.groupBox_labels); - - QWidget *containerTools = new QWidget; - QVBoxLayout *containerTools_layout = new QVBoxLayout; - containerTools_layout->addWidget(toolsSplitter); - containerTools_layout->addStretch(1); - containerTools->setLayout(containerTools_layout); - - - // mainSplitter->addWidget(containerTools); - mainSplitter->addWidget(containerAllViews); - - QGridLayout* grid = static_cast<QGridLayout*>(this->layout()); - grid->addWidget(containerTools); - grid->addWidget(mainSplitter); - - - - /* - * setting the size of the preview window - */ - //m_preview->view()->setFixedSize(450,302); - /* - * this triggers a better fitInView() but not enough for our purpose. - * See: http://stackoverflow.com/a/17085612 - */ - //m_preview->show(); - - /* - * setting the size of the viewport - * - * Details: - * The QGraphicsView is not the widget that actually contains the scene, - * because the QGraphicsView also manages the scrollbars. - * The scene is drawn in the viewport widget, - * which is a little smaller than the QGraphicsView. - * (http://qt-project.org/forums/viewthread/17504) - * - * Update: useful, but it's useless here, because we want to use fitInView() - * from the view, and that does not match with the viewport size. - */ - // m_preview->view()->viewport()->setFixedSize(400,265); - - - QSize size = m_preview->view()->maximumViewportSize(); - VP1Msg::message("scene rect: " + QString::number(m_scene->sceneRect().width()) + " - " + QString::number(m_scene->sceneRect().height()) ); - VP1Msg::message("max preview size: " + QString::number(size.width()) + " - " + QString::number(size.height()) ); - - m_preview->view()->ensureVisible ( m_scene->sceneRect(), 0, 0 ); - m_preview->view()->fitInView( m_scene->sceneRect(), Qt::KeepAspectRatio); - - // add a frame to preview to define the the rendering area - m_preview->addRenderingFrame(); - - // set the default m_scene bkg color: black - this->setBackgroundColor(); // the "black" checkbox is checked by default in the GUI - - setWindowIcon(QIcon(QString(":/vp1/icons/icons/3d_32x32.png"))); - - connect(m_d->ui.pushButton_get,SIGNAL(clicked()), this,SLOT(getTabSnapshot())); - -// connect(m_d->ui.pushButton_eventDetailsLabel,SIGNAL(clicked()), this,SLOT(getEventDetailsLabel())); - - - connect(m_d->ui.radioButton_eventDetails,SIGNAL(toggled(bool)), this,SLOT(enableCustomTextField(bool))); - // connect(m_d->ui.radioButton_customText,SIGNAL(toggled()), this,SLOT(showCustomTextField())); - - connect(m_d->ui.pushButton_addText,SIGNAL(clicked()), this,SLOT(setTextLabel())); - connect(m_d->ui.pushButton_removeObj,SIGNAL(clicked()), this,SLOT(removeObject())); - connect(m_d->ui.pushButton_addLogo,SIGNAL(clicked()), this,SLOT(addLogo())); - - connect(m_d->ui.pushButton_save,SIGNAL(clicked()), this,SLOT(savePicture())); - connect(m_d->ui.pushButton_print,SIGNAL(clicked()), this,SLOT(printPicture())); - - - connect(m_d->ui.radioButton_black,SIGNAL(clicked()), this,SLOT(setBackgroundColor())); - connect(m_d->ui.radioButton_white,SIGNAL(clicked()), this,SLOT(setBackgroundColor())); - connect(m_d->ui.radioButton_transparent,SIGNAL(clicked()), this,SLOT(setBackgroundColor())); - - this->setWindowTitle(tr("ATLAS VP1 Event Display Editor")); - - this->getEventDetailsLabel(); - - -} - -/* - * Qt example - */ -//VP1EventDisplayEditor::VP1EventDisplayEditor() -////: QWidget(0,Qt::WindowStaysOnTopHint), m_d(new Imp) -//: QWidget(0), m_d(new Imp) -//{ -// m_d->theclass = this; -// m_d->ui.setupUi(this); -// -// m_scene = new QGraphicsScene(); -// -// h1Splitter = new QSplitter; -// h2Splitter = new QSplitter; -// -// QSplitter *vSplitter = new QSplitter; -// vSplitter->setOrientation(Qt::Vertical); -// vSplitter->addWidget(h1Splitter); -// vSplitter->addWidget(h2Splitter); -// -// VP1EventDisplaySceneView *view = new VP1EventDisplaySceneView("Top left view"); -// view->view()->setScene(m_scene); -// h1Splitter->addWidget(view); -// -// view = new VP1EventDisplaySceneView("Top right view"); -// view->view()->setScene(m_scene); -// h1Splitter->addWidget(view); -// -// view = new VP1EventDisplaySceneView("Bottom left view"); -// view->view()->setScene(m_scene); -// h2Splitter->addWidget(view); -// -// view = new VP1EventDisplaySceneView("Bottom right view"); -// view->view()->setScene(m_scene); -// h2Splitter->addWidget(view); -// -// QLayout *layout = this->layout(); -// layout->addWidget(vSplitter); -//// setLayout(layout); -// -// setWindowTitle(tr("Chip Demo")); -// -// -//} - - - -//____________________________________________________________________ -VP1EventDisplayEditor::~VP1EventDisplayEditor() -{ - // m_d->frameHolderWidget->deleteLater(); - // foreach(VP1CustomTourFrameWidget*frame,m_d->frames) - // frame->deleteLater(); - delete m_d; - delete m_scene; - // delete scene_preview; -} - - -//____________________________________________________________________ -void VP1EventDisplayEditor::enableCustomTextField(bool checked) -{ -// if (m_d->ui.radioButton_eventDetails->isChecked()) - if (checked) - m_d->ui.lineEdit_customLabelText->setEnabled(false); - else - m_d->ui.lineEdit_customLabelText->setEnabled(true); -} - - -//____________________________________________________________________ -QString VP1EventDisplayEditor::getEventDetailsLabel() -{ - - QString evtstr = "Run: "+QString::number(m_runNumber)+"\n" - + "Event: "+QString::number(m_eventNumber)+"\n" - + QString(m_eventTimestamp>0 ? QDateTime::fromTime_t(m_eventTimestamp).toString(Qt::ISODate).replace('T',' ')+ " CEST" : ""); - - //VP1Msg::messageVerbose(evtstr); - - return evtstr; -} - - -//____________________________________________________________________ -void VP1EventDisplayEditor::printPicture() -{ - m_preview->print(); -} - - -//____________________________________________________________________ -void VP1EventDisplayEditor::savePicture() -{ - VP1Msg::messageVerbose("VP1EventDisplayEditor::savePicture()"); - - // hide the rendering frame, cause we do not want it in the final picture - m_preview->hideRenderingFrame(); - - QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), - "event_display.png", - tr("Images (*.png *.jpg)")); - - QImage image(m_scene->sceneRect().size().toSize(), QImage::Format_ARGB32); - image.fill(Qt::transparent); - - QPainter painter(&image); - painter.setRenderHint(QPainter::Antialiasing); - - m_scene->render(&painter); - - image.save(fileName); - - // show the rendering frame again - m_preview->showRenderingFrame(); - -} - - - - - - -//____________________________________________________________________ -void VP1EventDisplayEditor::addPixmapList(QList<QPixmap>& list, QStringList& listNames) -{ - VP1Msg::messageVerbose("VP1EventDisplayEditor::addPixmapList()"); - - if (!list.isEmpty()) { - foreach (QPixmap img, list) { - // add and set it movableimage to the scene - QGraphicsPixmapItem* item = m_scene->addPixmap(img); - item->setFlags(QGraphicsItem::ItemIsMovable); - m_sceneItems << item; - } - } - - if (!listNames.isEmpty()) { - foreach (QString name, listNames) { - // add image name to the list - new QListWidgetItem(name, m_d->ui.listWidget); - } - } -} - - -//____________________________________________________________________ -void VP1EventDisplayEditor::removeObject() -{ - QListWidgetItem * currentItem = m_d->ui.listWidget->currentItem(); - QString text = currentItem->text(); - int currentPos = m_d->ui.listWidget->row( currentItem ); - - // remove the object from the scene - m_scene->removeItem( m_sceneItems[currentPos] ); - // remove its associated pointer in our list - m_sceneItems.removeAt( currentPos ); - // remove its associated label - QListWidgetItem * item = m_d->ui.listWidget->takeItem(currentPos); - delete item; - - VP1Msg::message("Successfully removed the object: " + text); -} - -//// SLOT -////____________________________________________________________________ -//void VP1EventDisplayEditor::addTextLabelSlot() -//{ -// this->addTextLabel(); -//} - - -//____________________________________________________________________ -void VP1EventDisplayEditor::setTextLabel() -{ - QString text; - QFont font; - -// /* if we use this function programmatically, -// * passing text directly -// */ -// if (!textString.isEmpty()) { -// -// text = textString; -// -// // default settings -// int size = 32; -// int weight = QFont::Normal; -// bool italics = false; -// QString typeface = "Courier"; -// -// // default font -// font = QFont(typeface, size, weight, italics); -// -// // default font family, if Courier is not available -// font.setStyleHint(QFont::TypeWriter); -// -// } - -// /* if we use this function from the GUI, -// * then we get all user's settings from the GUI itself -// */ -// else { - - if (m_d->ui.radioButton_eventDetails->isChecked()) { - // get the event details - text = this->getEventDetailsLabel(); - } - else { - // get the user's text - text = m_d->ui.lineEdit_customLabelText->text(); - } - - - // get users' settings - int size = 0; - if (m_d->ui.radioButton_size12->isChecked()) size = 12; - else if (m_d->ui.radioButton_size24->isChecked()) size = 24; - else if (m_d->ui.radioButton_size32->isChecked()) size = 32; - else if (m_d->ui.radioButton_size44->isChecked()) size = 44; - else if (m_d->ui.radioButton_sizeCustom->isChecked()) { - size = m_d->ui.spinBox_size->value(); - } - - QString typeface = "Courier"; // default typeface - - int weight = QFont::Normal; - if (m_d->ui.radioButton_light->isChecked()) weight = QFont::Light; - else if (m_d->ui.radioButton_normal->isChecked()) weight = QFont::Normal; - else if (m_d->ui.radioButton_bold->isChecked()) weight = QFont::Bold; - else if (m_d->ui.radioButton_black_2->isChecked()) weight = QFont::Black; - - bool italics = false; - if (m_d->ui.radioButton_italics->isChecked()) italics = true; - - font = QFont(typeface, size, weight, italics); - - if (m_d->ui.radioButton_monaco->isChecked()) { - // typeface = "Monaco"; - typeface = "Courier"; - font.setStyleHint(QFont::TypeWriter); // this defines the family to choose from, if the preferred typeface is not available on the host system - } - else if (m_d->ui.radioButton_helvetica->isChecked()) { - typeface = "Helvetica"; - font.setStyleHint(QFont::SansSerif); - } - else if (m_d->ui.radioButton_times->isChecked()) { - typeface = "Times"; - font.setStyleHint(QFont::Serif); - } - font.setFamily(typeface); - -// } - - this->addTextLabel(text, font); -} - - -//____________________________________________________________________ -void VP1EventDisplayEditor::addTextLabel(QString text, QFont font) -{ -// adding the label to the m_scene -QGraphicsTextItem* item = m_scene->addText(text, font); -item->setFlags(QGraphicsItem::ItemIsMovable); - -// set the user's preferred color -if (m_d->ui.radioButton_whiteText->isChecked()) { - item->setDefaultTextColor(Qt::white); -} else if (m_d->ui.radioButton_blackText->isChecked()) { - item->setDefaultTextColor(Qt::black); -} - -// adding the label to the list of objects -QString strippedText = text.replace('\n',' ').replace('\t', ' ').simplified(); -new QListWidgetItem(strippedText, m_d->ui.listWidget); - -// adding the label to list of object pointers -m_sceneItems << item; -} - - -//____________________________________________________________________ -void VP1EventDisplayEditor::getTabSnapshot() -{ - int tabN = m_d->ui.comboBox_tabNumber->currentIndex(); - QString tabName = m_d->ui.comboBox_tabNumber->currentText(); - VP1Msg::messageVerbose("Got tab: " + tabName + " at idx: " + QString::number(tabN) ); - - int imageWidth = m_d->ui.spinBox_imageWidth->value(); - VP1Msg::messageVerbose("width: " + QString::number(imageWidth) ); - - QPixmap snap = m_mainWindow->getSingleChannelCustomSnapshot( tabName, imageWidth ); - - tabName = tabName + "_" + QString::number(imageWidth); - - - QList<QPixmap> listPixmap; - QStringList listNamesPixmap; - - listPixmap << snap; - listNamesPixmap << tabName; - - this->addPixmapList(listPixmap, listNamesPixmap); - -} - -//____________________________________________________________________ -void VP1EventDisplayEditor::setTabsList( QStringList listNames ) -{ - VP1Msg::messageVerbose("VP1EventDisplayEditor::setTabsList()"); - - m_d->ui.comboBox_tabNumber->addItems(listNames); - -} - - -//____________________________________________________________________ -void VP1EventDisplayEditor::addLogo() -{ - QPixmap pix; - QString name; - - // load the right version of the ATLAS logo - if ( m_d->ui.radioButton_300px->isChecked() ) { - if ( m_d->ui.radioButton_gray->isChecked() ) - pix.load(":/vp1/images/images/ATLAS-Logo-New_300pixels.png"); - if (m_d->ui.radioButton_blue->isChecked() ) - pix.load(":/vp1/images/images/ATLAS-chrome-logo-URL-blue_300px.png"); - name = "logo_300px"; - } - else if ( m_d->ui.radioButton_450px->isChecked() ) { - if ( m_d->ui.radioButton_gray->isChecked() ) - pix.load(":/vp1/images/images/ATLAS-Logo-New_450pixels.png"); - if (m_d->ui.radioButton_blue->isChecked() ) - pix.load(":/vp1/images/images/ATLAS-chrome-logo-URL-blue_450px.png"); - name = "logo_450px"; - } - else if ( m_d->ui.radioButton_600px->isChecked() ) { - if ( m_d->ui.radioButton_gray->isChecked() ) - pix.load(":/vp1/images/images/ATLAS-Logo-New_600pixels.png"); - if (m_d->ui.radioButton_blue->isChecked() ) - pix.load(":/vp1/images/images/ATLAS-chrome-logo-URL-blue_600px.png"); - name = "logo_600px"; - } - else if ( m_d->ui.radioButton_800px->isChecked() ) { - if ( m_d->ui.radioButton_gray->isChecked() ) - pix.load(":/vp1/images/images/ATLAS-Logo-New_800pixels.png"); -// if (m_d->ui.radioButton_blue->isChecked() ) -// pix.load(":/vp1/images/images/ATLAS-chrome-logo-URL-blue_600px.png"); - name = "logo_800px"; - } - else if ( m_d->ui.radioButton_1000px->isChecked() ) { - if ( m_d->ui.radioButton_gray->isChecked() ) - pix.load(":/vp1/images/images/ATLAS-Logo-New_1000pixels.png"); -// if (m_d->ui.radioButton_blue->isChecked() ) -// pix.load(":/vp1/images/images/ATLAS-chrome-logo-URL-blue_600px.png"); - name = "logo_1000px"; - } - else if ( m_d->ui.radioButton_1200px->isChecked() ) { - if ( m_d->ui.radioButton_gray->isChecked() ) - pix.load(":/vp1/images/images/ATLAS-Logo-New_1200pixels.png"); -// if (m_d->ui.radioButton_blue->isChecked() ) -// pix.load(":/vp1/images/images/ATLAS-chrome-logo-URL-blue_600px.png"); - name = "logo_1200px"; - } - - // add the logo to the m_scene - QGraphicsPixmapItem* item = m_scene->addPixmap(pix); - item->setFlags(QGraphicsItem::ItemIsMovable); - // add to the list of pointers - m_sceneItems << item; - // add to the list of object labels - new QListWidgetItem(name, m_d->ui.listWidget); -} - - -//____________________________________________________________________ -void VP1EventDisplayEditor::setBackgroundColor() -{ - - // a white background - if ( m_d->ui.radioButton_white->isChecked() ) - m_scene->setBackgroundBrush(Qt::white); - // a black background - else if ( m_d->ui.radioButton_black->isChecked() ) - m_scene->setBackgroundBrush(Qt::black); - // a transparent background - else if ( m_d->ui.radioButton_transparent->isChecked() ) { - m_scene->setBackgroundBrush(Qt::NoBrush); - // // a gradient background - // QRadialGradient gradient(0, 0, 10); - // gradient.setSpread(QGradient::RepeatSpread); - // m_scene->setBackgroundBrush(gradient); - } -} - - - -//____________________________________________________________________ -void VP1EventDisplayEditor::closeEvent(QCloseEvent*ev) -{ - // if you want to just hide the window when closed, uncomment the lines below - ev->ignore(); - hide(); - - // this, instead, will close the window - // ev->accept(); -} - -//QGraphicsView* VP1EventDisplayEditor::getView() -//{ -// return m_d->ui.graphicsView; -//} - - - - -////____________________________________________________________________ -//void VP1EventDisplayEditor::buttonClicked() -//{ -// if (m_d->ui.pushButton_addCurrentView==sender()) { -// VP1CustomTourFrameWidget * frame = new VP1CustomTourFrameWidget(m_d->viewer->currentCamIsPerspective(), -// m_d->viewer->currentCameraState()); -// m_d->addFrame(frame); -// m_d->updateFrameSnapshot(frame); -// m_d->updateFrameListVisuals(); -// } else if (m_d->ui.pushButton_refreshPreviews==sender()) { -// foreach(VP1CustomTourFrameWidget*frame,m_d->frames) -// m_d->updateFrameSnapshot(frame); -// } else if (m_d->ui.pushButton_execute==sender()) { -// m_d->viewer->startCustomTour(); -// } else if (m_d->ui.pushButton_utilityZoomShow==sender()) { -// } -//} - diff --git a/GeoModelVisualization/VP1Gui/src/VP1EventDisplaySceneView.cxx b/GeoModelVisualization/VP1Gui/src/VP1EventDisplaySceneView.cxx deleted file mode 100644 index 0c297f71035f5ae92dccbb7e9b36db36acd96bfd..0000000000000000000000000000000000000000 --- a/GeoModelVisualization/VP1Gui/src/VP1EventDisplaySceneView.cxx +++ /dev/null @@ -1,373 +0,0 @@ -/* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -*/ - -/* - * jira_1 - * VP1EventDisplaySceneView.cxx - * - * Created on: Sep 26, 2013 - * Author: rbianchi <Riccardo.Maria.Bianchi@cern.ch> - * - */ - -#include "VP1Gui/VP1EventDisplaySceneView.h" -#include "VP1Base/VP1Msg.h" - -#include <QtGui> -#include <QPrinter> -#include <QPrintDialog> - -#ifndef QT_NO_OPENGL - #include <QtOpenGL> -#endif - -#include <qmath.h> - -// with this we can use the mouse central wheel on the zoom sliders -void GraphicsView::wheelEvent(QWheelEvent *e) -{ - if (e->modifiers() & Qt::ControlModifier) { - if (e->delta() > 0) - m_view->zoomIn(6); - else - m_view->zoomOut(6); - e->accept(); - } else { - QGraphicsView::wheelEvent(e); - } -} - -VP1EventDisplaySceneView::VP1EventDisplaySceneView(const QString &name, bool preview, QWidget *parent) -: QFrame(parent),m_frame(nullptr),m_line(nullptr) -{ - m_preview = preview; - - - setFrameStyle(Sunken | StyledPanel); - - m_graphicsView = new GraphicsView(this); - m_graphicsView->setRenderHint(QPainter::Antialiasing, false); - m_graphicsView->setDragMode(QGraphicsView::RubberBandDrag); - m_graphicsView->setOptimizationFlags(QGraphicsView::DontSavePainterState); - m_graphicsView->setViewportUpdateMode(QGraphicsView::SmartViewportUpdate); - m_graphicsView->setTransformationAnchor(QGraphicsView::AnchorUnderMouse); - - int size = style()->pixelMetric(QStyle::PM_ToolBarIconSize); - QSize iconSize(size, size); - - - // ZOOM BUTTONS - - m_zoomInIcon = new QToolButton; - m_zoomInIcon->setAutoRepeat(true); - m_zoomInIcon->setAutoRepeatInterval(33); - m_zoomInIcon->setAutoRepeatDelay(0); - m_zoomInIcon->setIcon(QPixmap(":/vp1/icons/icons/zoomin.png")); - m_zoomInIcon->setIconSize(iconSize); - - m_zoomOutIcon = new QToolButton; - m_zoomOutIcon->setAutoRepeat(true); - m_zoomOutIcon->setAutoRepeatInterval(33); - m_zoomOutIcon->setAutoRepeatDelay(0); - m_zoomOutIcon->setIcon(QPixmap(":/vp1/icons/icons/zoomout.png")); - m_zoomOutIcon->setIconSize(iconSize); - - m_zoomSlider = new QSlider(); - m_zoomSlider->setMinimum(0); - m_zoomSlider->setMaximum(500); - m_zoomSlider->setValue(250); - m_zoomSlider->setTickPosition(QSlider::TicksRight); - - // Zoom slider layout - m_zoomSliderLayout = new QVBoxLayout; - m_zoomSliderLayout->addWidget(m_zoomInIcon); - m_zoomSliderLayout->addWidget(m_zoomSlider); - m_zoomSliderLayout->addWidget(m_zoomOutIcon); - - - // ROTATION BUTTONS - m_rotateLeftIcon = new QToolButton(); - m_rotateLeftIcon->setIcon(QPixmap(":/vp1/icons/icons/rotateleft.png")); - m_rotateLeftIcon->setIconSize(iconSize); - - m_rotateRightIcon = new QToolButton(); - m_rotateRightIcon->setIcon(QPixmap(":/vp1/icons/icons/rotateright.png")); - m_rotateRightIcon->setIconSize(iconSize); - - m_rotateSlider = new QSlider(); - m_rotateSlider->setOrientation(Qt::Horizontal); - m_rotateSlider->setMinimum(-360); - m_rotateSlider->setMaximum(360); - m_rotateSlider->setValue(0); - m_rotateSlider->setTickPosition(QSlider::TicksBelow); - - // Rotate slider layout - m_rotateSliderLayout = new QHBoxLayout; - m_rotateSliderLayout->addWidget(m_rotateLeftIcon); - m_rotateSliderLayout->addWidget(m_rotateSlider); - m_rotateSliderLayout->addWidget(m_rotateRightIcon); - - m_resetButton = new QToolButton; - m_resetButton->setText(tr("Reset")); - m_resetButton->setEnabled(false); - - // Label layout - QHBoxLayout *labelLayout = new QHBoxLayout; - m_label = new QLabel(name); - m_label2 = new QLabel(tr("Pointer Mode")); - - m_selectModeButton = new QToolButton; - m_selectModeButton->setText(tr("Select & Move items")); - m_selectModeButton->setCheckable(true); - m_selectModeButton->setChecked(true); - - m_dragModeButton = new QToolButton; - m_dragModeButton->setText(tr("Drag View")); - m_dragModeButton->setCheckable(true); - m_dragModeButton->setChecked(false); - - m_antialiasButton = new QToolButton; - m_antialiasButton->setText(tr("Antialiasing")); - m_antialiasButton->setCheckable(true); - m_antialiasButton->setChecked(false); - - m_openGlButton = new QToolButton; - m_openGlButton->setText(tr("OpenGL")); - m_openGlButton->setCheckable(true); -#ifndef QT_NO_OPENGL - m_openGlButton->setEnabled(QGLFormat::hasOpenGL()); -#else - m_openGlButton->setEnabled(false); -#endif - m_printButton = new QToolButton; - m_printButton->setIcon(QIcon(QPixmap(":/vp1/icons/icons/fileprint.png"))); - - QButtonGroup *pointerModeGroup = new QButtonGroup; - pointerModeGroup->setExclusive(true); - pointerModeGroup->addButton(m_selectModeButton); - pointerModeGroup->addButton(m_dragModeButton); - - labelLayout->addWidget(m_label); - labelLayout->addStretch(); - - if (!preview) { - labelLayout->addWidget(m_label2); - labelLayout->addWidget(m_selectModeButton); - labelLayout->addWidget(m_dragModeButton); - labelLayout->addStretch(); -// labelLayout->addWidget(m_antialiasButton); // we don't use these buttons -// labelLayout->addWidget(m_openGlButton); -// labelLayout->addWidget(m_printButton); - } - - QGridLayout *topLayout = new QGridLayout; - topLayout->addLayout(labelLayout, 0, 0); - topLayout->addWidget(m_graphicsView, 1, 0); - /* - * PREVIEW WINDOW - * we don't need the rotation or zoom buttons for the "preview" view - * and we put the reset button just below the zoom buttons - */ - if (preview) { - // m_zoomSliderLayout->addWidget(m_resetButton); - } - /* - * FULL SIZE WINDOW - */ - else { - topLayout->addLayout(m_zoomSliderLayout, 1, 1); - topLayout->addLayout(m_rotateSliderLayout, 2, 0); - topLayout->addWidget(m_resetButton, 2, 1); - } - - setLayout(topLayout); - - - - - connect(m_resetButton, SIGNAL(clicked()), this, SLOT(resetView())); - - connect(m_graphicsView->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(setResetButtonEnabled())); - connect(m_graphicsView->horizontalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(setResetButtonEnabled())); - - connect(m_selectModeButton, SIGNAL(toggled(bool)), this, SLOT(togglePointerMode())); - connect(m_dragModeButton, SIGNAL(toggled(bool)), this, SLOT(togglePointerMode())); - - connect(m_zoomSlider, SIGNAL(valueChanged(int)), this, SLOT(setupMatrix())); - connect(m_zoomInIcon, SIGNAL(clicked()), this, SLOT(zoomIn())); - connect(m_zoomOutIcon, SIGNAL(clicked()), this, SLOT(zoomOut())); - - connect(m_rotateSlider, SIGNAL(valueChanged(int)), this, SLOT(setupMatrix())); - connect(m_rotateLeftIcon, SIGNAL(clicked()), this, SLOT(rotateLeft())); - connect(m_rotateRightIcon, SIGNAL(clicked()), this, SLOT(rotateRight())); - - - // we do not use these three buttons now... -// connect(m_printButton, SIGNAL(clicked()), this, SLOT(print())); -// connect(m_antialiasButton, SIGNAL(toggled(bool)), this, SLOT(toggleAntialiasing())); -// connect(m_openGlButton, SIGNAL(toggled(bool)), this, SLOT(toggleOpenGL())); - - setupMatrix(); // only useful for the full-view window -} - -VP1EventDisplaySceneView::~VP1EventDisplaySceneView() -{ - /* if preview, many buttons are not added to any widget or layout, - * so we have to destroy them by hand - */ - if (m_preview) { - delete m_rotateSlider; - delete m_rotateLeftIcon; - delete m_rotateRightIcon; - delete m_rotateSliderLayout; - delete m_zoomSlider; - delete m_zoomInIcon; - delete m_zoomOutIcon; - delete m_zoomSliderLayout; - delete m_resetButton; - delete m_label2; - delete m_selectModeButton; - delete m_dragModeButton; - } - /* - * we have to destroy them by hand, because we do not use them in this version of the GUI - */ - delete m_antialiasButton; - delete m_openGlButton; - delete m_printButton; -} - -QGraphicsView *VP1EventDisplaySceneView::view() const -{ - return static_cast<QGraphicsView *>(m_graphicsView); -} - -void VP1EventDisplaySceneView::addRenderingFrame() -{ -// adding a rect to the preview to define the rendering area -// QPen pen2(Qt::green, 5, Qt::DashDotLine, Qt::RoundCap, Qt::RoundJoin); - QPen pen(Qt::red, 5, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin); - QRectF sceneRect = m_graphicsView->scene()->sceneRect(); - m_frame = m_graphicsView->scene()->addRect( sceneRect, pen ); - - /* we also have to add a line on the bottom of the scene, - * since the bottom side of the frame will go out of the view, - * due to the thickness of the frame lines. - */ - qreal x1 = sceneRect.left(); - qreal y1 = sceneRect.bottom(); - qreal y2 = y1; - qreal x2 = sceneRect.right(); - - m_line = m_graphicsView->scene()->addLine( x1, y1, x2, y2, pen); -} - -void VP1EventDisplaySceneView::showRenderingFrame() -{ - m_frame->show(); - m_line->show(); -} - -void VP1EventDisplaySceneView::hideRenderingFrame() -{ - m_frame->hide(); - m_line->hide(); -} - - - -void VP1EventDisplaySceneView::resetView() -{ - m_zoomSlider->setValue(250); - m_rotateSlider->setValue(0); - setupMatrix(); - m_graphicsView->ensureVisible(QRectF(0, 0, 0, 0)); - - m_resetButton->setEnabled(false); -} - -void VP1EventDisplaySceneView::setResetButtonEnabled() -{ - m_resetButton->setEnabled(true); -} - -void VP1EventDisplaySceneView::setPreviewZoom(qreal xx) -{ - if (m_preview) { - QMatrix matrix; - matrix.scale(xx, xx); - m_graphicsView->setMatrix(matrix); - } else { - VP1Msg::message("Warning!! using setPreviewZoom() on a full-size view has no effect."); - } - -} - -void VP1EventDisplaySceneView::setupMatrix() -{ - if (!m_preview) { - QMatrix matrix; - qreal scale = qPow(qreal(2), (m_zoomSlider->value() - 250) / qreal(50)); - matrix.scale(scale, scale); - matrix.rotate(m_rotateSlider->value()); - - m_graphicsView->setMatrix(matrix); - setResetButtonEnabled(); - } - -} - -void VP1EventDisplaySceneView::togglePointerMode() -{ - m_graphicsView->setDragMode(m_selectModeButton->isChecked() - ? QGraphicsView::RubberBandDrag - : QGraphicsView::ScrollHandDrag); - m_graphicsView->setInteractive(m_selectModeButton->isChecked()); -} - -void VP1EventDisplaySceneView::toggleOpenGL() -{ -#ifndef QT_NO_OPENGL - m_graphicsView->setViewport(m_openGlButton->isChecked() ? new QGLWidget(QGLFormat(QGL::SampleBuffers)) : new QWidget); -#endif -} - -void VP1EventDisplaySceneView::toggleAntialiasing() -{ - m_graphicsView->setRenderHint(QPainter::Antialiasing, m_antialiasButton->isChecked()); -} - -void VP1EventDisplaySceneView::print() -{ -#ifndef QT_NO_PRINTER - QPrinter printer; - QPrintDialog dialog(&printer, this); - if (dialog.exec() == QDialog::Accepted) { - QPainter painter(&printer); - m_graphicsView->render(&painter); - } -#endif -} - -void VP1EventDisplaySceneView::zoomIn(int level) -{ - m_zoomSlider->setValue(m_zoomSlider->value() + level); -} - -void VP1EventDisplaySceneView::zoomOut(int level) -{ - m_zoomSlider->setValue(m_zoomSlider->value() - level); -} - -void VP1EventDisplaySceneView::rotateLeft() -{ - m_rotateSlider->setValue(m_rotateSlider->value() - 10); -} - -void VP1EventDisplaySceneView::rotateRight() -{ - m_rotateSlider->setValue(m_rotateSlider->value() + 10); -} - - diff --git a/GeoModelVisualization/VP1Gui/src/VP1Prioritiser.cxx b/GeoModelVisualization/VP1Gui/src/VP1Prioritiser.cxx index 7078c6977c225d13a8937bd23eeb40e972833723..5182c4ff4fd2ea430f97a1215f4ad848ec829e4c 100644 --- a/GeoModelVisualization/VP1Gui/src/VP1Prioritiser.cxx +++ b/GeoModelVisualization/VP1Gui/src/VP1Prioritiser.cxx @@ -20,6 +20,7 @@ #include <QSet> #include <map> #include <cassert> +#include <unistd.h> ///////////////////////////////////////////////////////////////////// //////////////////// Class VP1Prioritiser::Imp //////////////////// @@ -59,7 +60,7 @@ public: QHash<IVP1System*,SystemInfo*> sys2info; - QTime * stopwatch; + QTime stopwatch; IVP1System* currenttimedsystem; void updateSysinfoWithVisibilityState(const QSet<IVP1ChannelWidget*>& channels, @@ -128,7 +129,7 @@ inline void VP1Prioritiser::Imp::SystemInfo::addTimeMeasurement(const double&t) m_timemeasurements.dequeue(); QList<double> tmplist = m_timemeasurements; - qSort(tmplist.begin(), tmplist.end()); + std::sort(tmplist.begin(), tmplist.end()); switch(tmplist.count()) { case 1: m_timing = tmplist.at(0); break; @@ -191,7 +192,6 @@ VP1Prioritiser::VP1Prioritiser(QObject*parent) : QObject(parent), m_d(new Imp) { m_d->prioritiser=this; - m_d->stopwatch = new QTime(); m_d->currenttimedsystem=0; m_d->soonvisbonus=0; } @@ -199,7 +199,6 @@ VP1Prioritiser::VP1Prioritiser(QObject*parent) //____________________________________________________________________ VP1Prioritiser::~VP1Prioritiser() { - delete m_d->stopwatch; delete m_d; m_d=0; } @@ -236,12 +235,12 @@ double VP1Prioritiser::estimateRemainingCalcTime() const } return tmp; } - +#include <iostream> //___________________________________________________________________ double VP1Prioritiser::beginTiming_Refresh(IVP1System*s) { assert(!m_d->currenttimedsystem); - m_d->stopwatch->start(); + m_d->stopwatch = QTime::currentTime(); m_d->currenttimedsystem=s; assert(m_d->sys2info.contains(s)); return m_d->sys2info[s]->refreshtime(); @@ -251,14 +250,17 @@ double VP1Prioritiser::beginTiming_Refresh(IVP1System*s) //___________________________________________________________________ double VP1Prioritiser::elapsedTiming_Refresh() { - return static_cast<double>(m_d->stopwatch->elapsed()); + QTime t=QTime::currentTime(); + double ms=static_cast<double>(m_d->stopwatch.msecsTo(t)); + return ms; } //___________________________________________________________________ double VP1Prioritiser::endTiming_Refresh() { assert(m_d->currenttimedsystem); - double timing = static_cast<double>(m_d->stopwatch->elapsed()); + QTime t=QTime::currentTime(); + double timing = static_cast<double>(m_d->stopwatch.msecsTo(t)); if (m_d->sys2info.contains(m_d->currenttimedsystem)) {//This check, since the corresponding channel might have become uncreated in the meantime. m_d->sys2info[m_d->currenttimedsystem]->addTimeMeasurement(timing); } diff --git a/GeoModelVisualization/VP1Gui/src/VP1TabManager.cxx b/GeoModelVisualization/VP1Gui/src/VP1TabManager.cxx index 73d8e3d8cc53a9bc58bc4b5a49e335e805b861ef..c79023a67fc4f6dcd268f71f206228ce8a5579ff 100644 --- a/GeoModelVisualization/VP1Gui/src/VP1TabManager.cxx +++ b/GeoModelVisualization/VP1Gui/src/VP1TabManager.cxx @@ -31,6 +31,7 @@ #include <QSet> #include <QFileInfo> #include <QMap> +#include <QMultiMap> #include <QTimer> #include <QBuffer> #include <QByteArray> @@ -723,9 +724,11 @@ void VP1TabManager::cloneChannelToTab(QString channeluniquename,QString tabname) assert(cw); IVP1ChannelWidget * newcw = addChannelToTab(cw->name(),tabname); if (newcw) { +#ifdef SAVEANDRESTORE ChanState state; serializeChannelState(cw,state); unserializeChannelState(newcw,state); +#endif } } @@ -748,9 +751,11 @@ void VP1TabManager::cloneTab(QString oldtabname,QString newtabname) for (;it!=itE;++it) { IVP1ChannelWidget * newcw = addChannelToTab((*it)->name(),newtabname); if (newcw) { +#ifdef SAVEANDRESTORE ChanState state; serializeChannelState(*it,state); unserializeChannelState(newcw,state); +#endif } } @@ -763,6 +768,8 @@ void VP1TabManager::cloneTab(QString oldtabname,QString newtabname) +#ifdef SAVEANDRESTORE + //___________________________________________________________________________________ void VP1TabManager::saveConfigurationToFile(QString filename,const bool& askonoverride) { if (filename.isEmpty()) { @@ -819,7 +826,6 @@ void VP1TabManager::saveConfigurationToFile(QString filename,const bool& askonov } - //___________________________________________________________________________________ void VP1TabManager::loadConfigurationFromFile(QString filename,const QMap<QString,QString>& availableplugins) { if (filename.isEmpty()) { @@ -954,8 +960,9 @@ void VP1TabManager::loadConfigurationFromFile(QString filename,const QMap<QStrin return; lastaddedtab=newtabname; - QMapIterator<QString,ChanState> it( tab2channels.value(newtabname_infile) ); - + // QMapIterator<QString,ChanState> + // auto + QMultiMap<QString, std::pair<QByteArray, QMultiMap<QString, QByteArray> > >it=( tab2channels.value(newtabname_infile) ); while (it.hasNext()) { it.next(); //it.key(): Channel base name. @@ -995,6 +1002,7 @@ void VP1TabManager::loadConfigurationFromFile(QString filename,const QMap<QStrin if (!lastaddedtab.isEmpty()) showTab(lastaddedtab); } +#endif //___________________________________________________________________________________ void VP1TabManager::Imp::serializeTabAndChannelConfigInfo(QMap<QString,QMultiMap<QString,ChanState> >& tab2channels, @@ -1012,9 +1020,11 @@ void VP1TabManager::Imp::serializeTabAndChannelConfigInfo(QMap<QString,QMultiMap std::set<IVP1ChannelWidget*>::const_iterator it = itcws->second.begin(); std::set<IVP1ChannelWidget*>::const_iterator itE = itcws->second.end(); for (;it!=itE;++it) { +#ifdef SAVEANDRESTORE ChanState chanstate; tabmanager->serializeChannelState(*it,chanstate); channelsinfo.insert((*it)->name(),chanstate); +#endif } tab2channels.insert(tabname,channelsinfo); @@ -1023,6 +1033,7 @@ void VP1TabManager::Imp::serializeTabAndChannelConfigInfo(QMap<QString,QMultiMap } } + //___________________________________________________________________________________ QString VP1TabManager::suggestNewTabName(QString oldtabname) const { QString newtabname=oldtabname; @@ -1521,6 +1532,7 @@ void VP1TabManager::executePendingChannelRemoval() m_d->channelWithPendingRemoval=""; } +#ifdef SAVEANDRESTORE //___________________________________________________________________________________ void VP1TabManager::serializeChannelState(IVP1ChannelWidget*cw,ChanState&state) { @@ -1578,3 +1590,4 @@ void VP1TabManager::unserializeChannelState(IVP1ChannelWidget*cw,ChanState state foreach (QString name,storedSystems) std::cout<<"VP1TabManager::unserializeChannelState Warning: Did not use stored configuration for system "<<name.toStdString()<<std::endl; } +#endif diff --git a/GeoModelVisualization/VP1GuideLineSystems/CMakeLists.txt b/GeoModelVisualization/VP1GuideLineSystems/CMakeLists.txt index d98bda0f416b421d68ec3c748961307cca883585..100e56767a93500eba655ffca38b6ce7b69346c0 100644 --- a/GeoModelVisualization/VP1GuideLineSystems/CMakeLists.txt +++ b/GeoModelVisualization/VP1GuideLineSystems/CMakeLists.txt @@ -8,7 +8,7 @@ file( GLOB UIS src/*.ui ) # Add the library. add_library( GXGuideLineSystems SHARED ${SOURCES} ${HEADERS} ${UIS} ) target_link_libraries( GXGuideLineSystems - PUBLIC Coin::Coin Qt5::Core Qt5::Gui Qt5::Widgets GXBase + PUBLIC Coin::Coin Qt${QT_VERSION}::Core Qt${QT_VERSION}::Gui Qt${QT_VERSION}::Widgets GXBase PRIVATE GeoModelCore::GeoModelKernel GXHEPVis ) target_include_directories( GXGuideLineSystems PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> diff --git a/GeoModelVisualization/cmake/GeoModelVisualizationConfig.cmake.in b/GeoModelVisualization/cmake/GeoModelVisualizationConfig.cmake.in index b81d6030b6bf7ffe0f58f59d9b820cb7198de50b..17d42aeaa69849264dc1464e8100a01cab608055 100644 --- a/GeoModelVisualization/cmake/GeoModelVisualizationConfig.cmake.in +++ b/GeoModelVisualization/cmake/GeoModelVisualizationConfig.cmake.in @@ -6,7 +6,7 @@ find_dependency( GeoModelCore @GeoModel_VERSION@ CONFIG EXACT ) find_dependency( GeoModelIO @GeoModel_VERSION@ CONFIG EXACT ) find_dependency( Coin3D ) find_dependency( SoQt ) -find_dependency( Qt5 @Qt5_VERSION@ +find_dependency( Qt6 @Qt6_VERSION@ COMPONENTS Core Gui Widgets Sql PrintSupport EXACT ) find_dependency( OpenGL ) diff --git a/README.md b/README.md index 3037e1e1bd5cc53426d0e293db3cc52742da2181..99998dd4b8f8f219c129df0c976ab5c331c708fb 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ +[](https://gitlab.cern.ch/GeoModelDev/GeoModel/-/releases) [](https://gitlab.cern.ch/GeoModelDev/GeoModel/-/commits/master) + # GeoModel --- A user-friendly C++ Toolkit for HEP Detector Description GeoModel is a user-friendly C++ Toolkit and Suite for HEP Detector Description with minimal dependencies. diff --git a/cmake/BuildType.cmake b/cmake/BuildType.cmake index 14a12a8ccc0c22511e31288d7ab3b4fea69fb561..ac66a37a7ee18d873e34487b35740b9178027783 100644 --- a/cmake/BuildType.cmake +++ b/cmake/BuildType.cmake @@ -14,15 +14,9 @@ set(default_build_type "Release") # endif() if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - if( COLOR_DEFS ) - message(STATUS "${Blue}INFO: Setting build type to '${default_build_type}' as none was specified.${ColourReset}") - else() - message(STATUS "INFO: Setting build type to '${default_build_type}' as none was specified.") - endif() - set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE - STRING "Choose the type of build." FORCE) + message(STATUS "${Blue}INFO: Setting build type to '${default_build_type}' as none was specified.${ColourReset}") + set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE STRING "Choose the type of build." FORCE) # Set the possible values of build type for cmake-gui - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS - "Debug" "Release" "MinSizeRel" "RelWithDebInfo") + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") endif() diff --git a/cmake/GeoModel-version.cmake b/cmake/GeoModel-version.cmake index f9be66722228c2e3a6b2dba0ee6e9d9f46ac27ad..a8904ac5aa0390e5aff8663538ada40e57bca9b6 100644 --- a/cmake/GeoModel-version.cmake +++ b/cmake/GeoModel-version.cmake @@ -1,5 +1,5 @@ # Set up the version of GeoModel as a cache variable, so that other # sub-projects could use this value. -set( GeoModel_VERSION "4.4.5" CACHE STRING +set( GeoModel_VERSION "5.0.0" CACHE STRING "Version of the GeoModel project" ) diff --git a/cmake/PrintBuildInfo.cmake b/cmake/PrintBuildInfo.cmake index 862a34b45c7506c83a229d7ef71ff604d182acb6..68d6ac021630eea3a87ec51a01544965cd7238a6 100644 --- a/cmake/PrintBuildInfo.cmake +++ b/cmake/PrintBuildInfo.cmake @@ -1,13 +1,6 @@ # Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration -if( COLOR_DEFS ) - message(STATUS "-----") - message(STATUS "${BoldYellow}Building with type: ${CMAKE_BUILD_TYPE}${ColourReset}") - message(STATUS "${BoldYellow}Using C++ standard: ${CMAKE_CXX_STANDARD}${ColourReset}") - message(STATUS "-----") -else() - message(STATUS "-----") - message(STATUS "Building with type: ${CMAKE_BUILD_TYPE}") - message(STATUS "Using C++ standard: ${CMAKE_CXX_STANDARD}") - message(STATUS "-----") -endif() +message(STATUS "-----") +message(STATUS "${BoldYellow}Building with type: ${CMAKE_BUILD_TYPE}${ColourReset}") +message(STATUS "${BoldYellow}Using C++ standard: ${CMAKE_CXX_STANDARD}${ColourReset}") +message(STATUS "-----") diff --git a/cmake/SetupCoin3D.cmake b/cmake/SetupCoin3D.cmake index d8372de2a0ac68c3e97a7df3bbf6891cc06dbe2b..98d818f55d62689c87acbffa67c1077e43d6a3dc 100644 --- a/cmake/SetupCoin3D.cmake +++ b/cmake/SetupCoin3D.cmake @@ -20,11 +20,7 @@ option( GEOMODEL_USE_BUILTIN_COIN3D if( GEOMODEL_USE_BUILTIN_COIN3D ) # Tell the user what's happening. - if( COLOR_DEFS ) - message( STATUS "${BoldMagenta}'GEOMODEL_USE_BUILTIN_COIN3D' was set to 'true' ==> Building Coin and SoQt as part of the project${ColourReset}" ) - else() - message( STATUS "'GEOMODEL_USE_BUILTIN_COIN3D' was set to 'true' ==> Building Coin and SoQt as part of the project" ) - endif() + message( STATUS "${BoldMagenta}'GEOMODEL_USE_BUILTIN_COIN3D' was set to 'true' ==> Building Coin and SoQt as part of the project${ColourReset}" ) # External(s) required for the build. find_package( Boost REQUIRED ) diff --git a/cmake/SetupEigen3.cmake b/cmake/SetupEigen3.cmake index 9e64412ea08586b91f8e328b26a3cf0f85016401..6e3079f62fa6db81850abef92a05327f2e9d3603 100644 --- a/cmake/SetupEigen3.cmake +++ b/cmake/SetupEigen3.cmake @@ -5,60 +5,51 @@ # # Make sure that this file is only included once. -get_property( _eigenSetUp GLOBAL PROPERTY GEOMODEL_EIGEN_SET_UP SET ) -if( _eigenSetUp ) - unset( _eigenSetUp ) - return() -endif() -set_property( GLOBAL PROPERTY GEOMODEL_EIGEN_SET_UP TRUE ) +include_guard(GLOBAL) # Configuration option for how Eigen should be used. -option( GEOMODEL_USE_BUILTIN_EIGEN3 - "Download a version of Eigen3 during the build" FALSE ) +option(GEOMODEL_USE_BUILTIN_EIGEN3 "Download a version of Eigen3 during the build" OFF) # Now do what was requested. if( GEOMODEL_USE_BUILTIN_EIGEN3 ) - - # Tell the user what's happening. - message( STATUS "Building Eigen3 as part of the project" ) - - # Helper variables for the Eigen build. - set( Eigen3_INCLUDE_DIR - "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/Eigen3Install/include/eigen3" ) - set( Eigen3_VERSION "3.2.9" ) - - # Create the include directory already, otherwise CMake refuses to - # create the imported target. - file( MAKE_DIRECTORY "${Eigen3_INCLUDE_DIR}" ) - - # Build/install Eigen3 using ExternalProject_Add(...). - include( ExternalProject ) - ExternalProject_Add( Eigen3 - PREFIX ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/Eigen3Build - INSTALL_DIR ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/Eigen3Install - URL "http://cern.ch/lcgpackages/tarFiles/sources/eigen-${Eigen3_VERSION}.tar.gz" - URL_MD5 "de04f424e6b86907ccc9737b5d3048e7" - CMAKE_CACHE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> - BUILD_BYPRODUCTS "${Eigen3_INCLUDE_DIR}" ) - ExternalProject_Add_Step( Eigen3 removepc - COMMAND ${CMAKE_COMMAND} -E remove_directory <INSTALL_DIR>/share - COMMENT "Removing the pkgconfig file from Eigen" - DEPENDEES install ) - install( DIRECTORY - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/Eigen3Install/ - DESTINATION . - COMPONENT Development - USE_SOURCE_PERMISSIONS ) - - # Set up an imported target that mimicks the one created by the exported - # CMake configuration of an Eigen installation. - add_library( Eigen3::Eigen INTERFACE IMPORTED ) - set_target_properties( Eigen3::Eigen PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${Eigen3_INCLUDE_DIR}" ) - + # Tell the user what's happening. + message( STATUS "Building Eigen3 as part of the project" ) + + # Helper variables for the Eigen build. + set( Eigen3_INCLUDE_DIR "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/Eigen3Install/include/eigen3" ) + set( Eigen3_VERSION "3.2.9" ) + + # Create the include directory already, otherwise CMake refuses to + # create the imported target. + file( MAKE_DIRECTORY "${Eigen3_INCLUDE_DIR}" ) + + # Build/install Eigen3 using ExternalProject_Add(...). + include( ExternalProject ) + ExternalProject_Add( Eigen3 + PREFIX ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/Eigen3Build + INSTALL_DIR ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/Eigen3Install + URL "http://cern.ch/lcgpackages/tarFiles/sources/eigen-${Eigen3_VERSION}.tar.gz" + URL_MD5 "de04f424e6b86907ccc9737b5d3048e7" + CMAKE_CACHE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> + BUILD_BYPRODUCTS "${Eigen3_INCLUDE_DIR}" ) + ExternalProject_Add_Step( Eigen3 removepc + COMMAND ${CMAKE_COMMAND} -E remove_directory <INSTALL_DIR>/share + COMMENT "Removing the pkgconfig file from Eigen" + DEPENDEES install ) + install( DIRECTORY + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/Eigen3Install/ + DESTINATION . + COMPONENT Development + USE_SOURCE_PERMISSIONS ) + + # Set up an imported target that mimicks the one created by the exported + # CMake configuration of an Eigen installation. + add_library( Eigen3::Eigen INTERFACE IMPORTED ) + set_target_properties( Eigen3::Eigen PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${Eigen3_INCLUDE_DIR}" ) + + # Add dependency to the underlying external project + add_dependencies(Eigen3::Eigen Eigen3) else() - - # Just find an existing installation of Eigen3. - find_package( Eigen3 REQUIRED NO_MODULE ) - + # Just find an existing installation of Eigen3. + find_package( Eigen3 REQUIRED NO_MODULE ) endif() diff --git a/cmake/SetupJSON.cmake b/cmake/SetupJSON.cmake index 3e6312b0df7f06bdcf1279e756def2a540da9ae9..6eb203ecf9a84b77d2f1138a5cf7b6c7197e485c 100644 --- a/cmake/SetupJSON.cmake +++ b/cmake/SetupJSON.cmake @@ -6,79 +6,54 @@ # # Make sure that this file is only included once. -get_property( _jsonSetUp GLOBAL PROPERTY GEOMODEL_JSON_SET_UP SET ) -if( _jsonSetUp ) - unset( _jsonSetUp ) - return() -endif() -set_property( GLOBAL PROPERTY GEOMODEL_JSON_SET_UP TRUE ) +include_guard(GLOBAL) # Configuration option for how "nlohmann_json" should be used. -option( GEOMODEL_USE_BUILTIN_JSON -"Download and compile a version of nlohmann_json during the build" FALSE ) +option(GEOMODEL_USE_BUILTIN_JSON "Download and compile a version of nlohmann_json during the build" OFF) # Now do what was requested. -if( GEOMODEL_USE_BUILTIN_JSON ) - +if(GEOMODEL_USE_BUILTIN_JSON) # Tell the user what's happening. - if( COLOR_DEFS ) - message( STATUS "${BoldMagenta}'GEOMODEL_USE_BUILTIN_JSON' was set to 'true' ==> Building nlohmann_json as part of the project${ColourReset}" ) - else() - message( STATUS "'GEOMODEL_USE_BUILTIN_JSON' was set to 'true' ==> Building nlohmann_json as part of the project" ) - endif() + message( STATUS "${BoldMagenta}'GEOMODEL_USE_BUILTIN_JSON' was set to 'true' ==> Building nlohmann_json as part of the project${ColourReset}" ) # The include directory and library that will be produced. - set( nlohmann_json_INCLUDE_DIR - "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/JSONInstall/${CMAKE_INSTALL_INCLUDEDIR}" ) - set( nlohmann_json_INCLUDE_DIRS "${nlohmann_json_INCLUDE_DIR}" ) - set( nlohmann_json_VERSION "3.6.1" ) - set( nlohmann_json_FOUND TRUE ) + set(nlohmann_json_INCLUDE_DIR "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/JSONInstall/${CMAKE_INSTALL_INCLUDEDIR}" ) + set(nlohmann_json_INCLUDE_DIRS "${nlohmann_json_INCLUDE_DIR}" ) + set(nlohmann_json_VERSION "3.6.1" ) + set(nlohmann_json_FOUND TRUE ) message(STATUS "Installing the built-in 'nlohmann_json' in: ${nlohmann_json_INCLUDE_DIR}") # Create the include directory already, otherwise CMake refuses to # create the imported target. - file( MAKE_DIRECTORY "${nlohmann_json_INCLUDE_DIR}" ) + file(MAKE_DIRECTORY "${nlohmann_json_INCLUDE_DIR}") # Build/install nlohmann_json using ExternalProject_Add(...). include( ExternalProject ) - ExternalProject_Add( JSONExt - PREFIX ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/JSONBuild - INSTALL_DIR ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/JSONInstall - URL "https://cern.ch/lcgpackages/tarFiles/sources/json-${nlohmann_json_VERSION}.tar.gz" - URL_MD5 "c53592d55e7fec787cf0a406d36098a3" - CMAKE_CACHE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> - -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} - -DCMAKE_CXX_STANDARD:STRING=${CMAKE_CXX_STANDARD} - -DJSON_BuildTests:BOOL=OFF -DJSON_MultipleHeaders:BOOL=ON - BUILD_BYPRODUCTS "${nlohmann_json_INCLUDE_DIR}" ) - install( DIRECTORY - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/JSONInstall/ - DESTINATION . - COMPONENT Development - USE_SOURCE_PERMISSIONS ) + ExternalProject_Add(JSONExt + PREFIX ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/JSONBuild + INSTALL_DIR ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/JSONInstall + URL "https://cern.ch/lcgpackages/tarFiles/sources/json-${nlohmann_json_VERSION}.tar.gz" + URL_MD5 "c53592d55e7fec787cf0a406d36098a3" + CMAKE_CACHE_ARGS + -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> + -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} + -DCMAKE_CXX_STANDARD:STRING=${CMAKE_CXX_STANDARD} + -DJSON_BuildTests:BOOL=OFF + -DJSON_MultipleHeaders:BOOL=ON + BUILD_BYPRODUCTS "${nlohmann_json_INCLUDE_DIR}" ) + install(DIRECTORY ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/JSONInstall/ + DESTINATION . + COMPONENT Development + USE_SOURCE_PERMISSIONS) # Set up nlohmann_json's imported target. - add_library( nlohmann_json::nlohmann_json INTERFACE IMPORTED ) - set_target_properties( nlohmann_json::nlohmann_json PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${nlohmann_json_INCLUDE_DIR}" ) + add_library(nlohmann_json::nlohmann_json INTERFACE IMPORTED) + set_property(TARGET nlohmann_json::nlohmann_json PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${nlohmann_json_INCLUDE_DIR}") + + # Auto handle dependency + add_dependencies(nlohmann_json::nlohmann_json JSONExt) else() - # Find an existing installation of nlohmann_json. - find_package( nlohmann_json QUIET ) - if( nlohmann_json_FOUND ) - # If it was found, tell the user about it. - get_target_property( _incPaths nlohmann_json::nlohmann_json - INTERFACE_INCLUDE_DIRECTORIES ) - list( GET _incPaths 0 _incPath ) - message( STATUS "Found nlohmann_json: ${_incPath}" ) - unset( _incPaths ) - unset( _incPath ) - else() - # If it was not found, it may still be that the necessary header is - # available on the build system. So just set up a dummy library that would - # allow the configuration to succeed. - message( WARNING "Creating a dummy nlohmann_json::nlohmann_json target " - "in case the headers are avalable in some public place..." ) - add_library( nlohmann_json::nlohmann_json INTERFACE IMPORTED ) - endif() + # Find an existing installation of nlohmann_json. + find_package(nlohmann_json REQUIRED) endif() diff --git a/cmake/SetupXercesC.cmake b/cmake/SetupXercesC.cmake index da6ec6fda361b2fd23da6cbe07b0cbabc3542f2a..c03ef2722fe3b910e5e9a943da1e43aaca6b465a 100644 --- a/cmake/SetupXercesC.cmake +++ b/cmake/SetupXercesC.cmake @@ -4,78 +4,63 @@ # it on the build machine, or by downloading it during the build itself. # -# Make sure that this file is only included once. -get_property( _xercescSetUp GLOBAL PROPERTY GEOMODEL_XERCESC_SET_UP SET ) -if( _xercescSetUp ) - unset( _xercescSetUp ) - return() -endif() -set_property( GLOBAL PROPERTY GEOMODEL_XERCESC_SET_UP TRUE ) +# Make sure that this file is only included once.] +include_guard(GLOBAL) # Configuration option for how XercesC should be used. -option( GEOMODEL_USE_BUILTIN_XERCESC - "Download/build a version of XercesC during the build" FALSE ) +option( GEOMODEL_USE_BUILTIN_XERCESC "Download/build a version of XercesC during the build" OFF) # Now do what was requested. -if( GEOMODEL_USE_BUILTIN_XERCESC ) +if(GEOMODEL_USE_BUILTIN_XERCESC) - # Tell the user what's happening. - if( COLOR_DEFS ) - message( STATUS "${BoldMagenta}'GEOMODEL_USE_BUILTIN_XERCESC' was set to 'true' ==> Building XercesC as part of the project${ColourReset}" ) - else() - message( STATUS "'GEOMODEL_USE_BUILTIN_XERCESC' was set to 'true' ==> Building XercesC as part of the project" ) - endif() + # Tell the user what's happening. + message( STATUS "${BoldMagenta}'GEOMODEL_USE_BUILTIN_XERCESC' was set to 'true' ==> Building XercesC as part of the project${ColourReset}" ) - # The include directory and library that will be produced. - set( XercesC_INCLUDE_DIR - "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/XercesCInstall/${CMAKE_INSTALL_INCLUDEDIR}" CACHE PATH "Path to the Xerces-C include directory" FORCE ) - set( XercesC_INCLUDE_DIRS "${XercesC_INCLUDE_DIR}" ) - set( XercesC_LIBRARY - "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/XercesCInstall/lib/${CMAKE_SHARED_LIBRARY_PREFIX}xerces-c${CMAKE_SHARED_LIBRARY_SUFFIX}" CACHE PATH "Path to the Xerces-C library file" FORCE ) - set( XercesC_LIBRARIES "${XercesC_LIBRARY}" ) - set( XercesC_LIBRARY_RELEASE "${XercesC_LIBRARY}" CACHE PATH "Path to the Xerces-C library" FORCE ) - set( XercesC_VERSION "3.2.3" ) + # The include directory and library that will be produced. + set(XercesC_INCLUDE_DIR "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/XercesCInstall/${CMAKE_INSTALL_INCLUDEDIR}" CACHE PATH "Path to the Xerces-C include directory" FORCE ) + set(XercesC_INCLUDE_DIRS "${XercesC_INCLUDE_DIR}" ) + set(XercesC_LIBRARY "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/XercesCInstall/lib/${CMAKE_SHARED_LIBRARY_PREFIX}xerces-c${CMAKE_SHARED_LIBRARY_SUFFIX}" CACHE PATH "Path to the Xerces-C library file" FORCE ) + set(XercesC_LIBRARIES "${XercesC_LIBRARY}" ) + set(XercesC_LIBRARY_RELEASE "${XercesC_LIBRARY}" CACHE PATH "Path to the Xerces-C library" FORCE ) + set(XercesC_VERSION "3.2.3" ) - # Create the include directory already, otherwise CMake refuses to - # create the imported target. - file( MAKE_DIRECTORY "${XercesC_INCLUDE_DIR}" ) + # Create the include directory already, otherwise CMake refuses to + # create the imported target. + file( MAKE_DIRECTORY "${XercesC_INCLUDE_DIR}" ) - # Build/install Eigen3 using ExternalProject_Add(...). - include( ExternalProject ) - ExternalProject_Add( XercesCBuiltIn - PREFIX "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/XercesCBuild" - INSTALL_DIR "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/XercesCInstall" - URL "https://cern.ch/lcgpackages/tarFiles/sources/xerces-c-${XercesC_VERSION}.tar.gz" - URL_MD5 "a5fa4d920fce31c9ca3bfef241644494" - CONFIGURE_COMMAND - ${CMAKE_COMMAND} -E env CXXFLAGS=-std=c++${CMAKE_CXX_STANDARD} - <SOURCE_DIR>/configure --disable-static --prefix=<INSTALL_DIR> - INSTALL_COMMAND make install - COMMAND ${CMAKE_COMMAND} -E remove -f - "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/XercesCInstall/lib/${CMAKE_SHARED_LIBRARY_PREFIX}xerces-c.la" - COMMAND ${CMAKE_COMMAND} -E remove_directory - "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/XercesCInstall/lib/pkgconfig" - BUILD_BYPRODUCTS "${XercesC_INCLUDE_DIR}" "${XercesC_LIBRARY}" ) - install( DIRECTORY - "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/XercesCInstall/bin" - "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/XercesCInstall/lib" - DESTINATION . - COMPONENT Runtime - USE_SOURCE_PERMISSIONS ) - install( DIRECTORY "${XercesC_INCLUDE_DIR}" - DESTINATION . - COMPONENT Development - USE_SOURCE_PERMISSIONS ) + # Build/install XercesC using ExternalProject_Add(...). + include(ExternalProject) + ExternalProject_Add( XercesCBuiltIn + PREFIX "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/XercesCBuild" + INSTALL_DIR "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/XercesCInstall" + URL "https://cern.ch/lcgpackages/tarFiles/sources/xerces-c-${XercesC_VERSION}.tar.gz" + URL_MD5 "a5fa4d920fce31c9ca3bfef241644494" + CONFIGURE_COMMAND + ${CMAKE_COMMAND} -E env CXXFLAGS=-std=c++${CMAKE_CXX_STANDARD} <SOURCE_DIR>/configure --disable-static --prefix=<INSTALL_DIR> + INSTALL_COMMAND make install + COMMAND ${CMAKE_COMMAND} -E remove -f "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/XercesCInstall/lib/${CMAKE_SHARED_LIBRARY_PREFIX}xerces-c.la" + COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/XercesCInstall/lib/pkgconfig" + BUILD_BYPRODUCTS "${XercesC_INCLUDE_DIR}" "${XercesC_LIBRARY}" ) + install(DIRECTORY + "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/XercesCInstall/bin" + "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/XercesCInstall/lib" + DESTINATION . + COMPONENT Runtime + USE_SOURCE_PERMISSIONS ) + install(DIRECTORY "${XercesC_INCLUDE_DIR}" + DESTINATION . + COMPONENT Development + USE_SOURCE_PERMISSIONS ) - # Set up XercesC's imported target. - add_library( XercesC::XercesC UNKNOWN IMPORTED ) - set_target_properties( XercesC::XercesC PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${XercesC_INCLUDE_DIR}" - IMPORTED_LOCATION "${XercesC_LIBRARY}" ) + # Set up local XercesC "imported" target. + add_library(XercesC::XercesC UNKNOWN IMPORTED) + set_target_properties( XercesC::XercesC PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${XercesC_INCLUDE_DIR}" + IMPORTED_LOCATION "${XercesC_LIBRARY}") + # Handle dependency to underlying external project + add_dependencies(XercesC::XercesC XercesCBuiltIn) else() - - # Just find an existing installation of XercesC. - find_package( XercesC REQUIRED ) - + # Just find an existing installation of XercesC. + find_package(XercesC REQUIRED) endif() diff --git a/cmake/cmake_colors_defs.cmake b/cmake/cmake_colors_defs.cmake index b6eea59ba9e72a50754ac0afb36d25cfcac59e09..a2d5414200d7d2d0a3d68b149bdd87df09ed481c 100644 --- a/cmake/cmake_colors_defs.cmake +++ b/cmake/cmake_colors_defs.cmake @@ -4,22 +4,24 @@ # Source: https://stackoverflow.com/a/19578320/320369 if(NOT WIN32) - set( COLOR_DEFS TRUE CACHE BOOL "Define color escape sequences to be used in CMake messages." ) - string(ASCII 27 Esc) - set(ColourReset "${Esc}[m") - set(ColourBold "${Esc}[1m") - set(Red "${Esc}[31m") - set(Green "${Esc}[32m") - set(Yellow "${Esc}[33m") - set(Blue "${Esc}[34m") - set(Magenta "${Esc}[35m") - set(Cyan "${Esc}[36m") - set(White "${Esc}[37m") - set(BoldRed "${Esc}[1;31m") - set(BoldGreen "${Esc}[1;32m") - set(BoldYellow "${Esc}[1;33m") - set(BoldBlue "${Esc}[1;34m") - set(BoldMagenta "${Esc}[1;35m") - set(BoldCyan "${Esc}[1;36m") - set(BoldWhite "${Esc}[1;37m") + set(COLOR_DEFS TRUE CACHE BOOL "Define color escape sequences to be used in CMake messages.") + if(COLOR_DEFS) + string(ASCII 27 Esc) + set(ColourReset "${Esc}[m") + set(ColourBold "${Esc}[1m") + set(Red "${Esc}[31m") + set(Green "${Esc}[32m") + set(Yellow "${Esc}[33m") + set(Blue "${Esc}[34m") + set(Magenta "${Esc}[35m") + set(Cyan "${Esc}[36m") + set(White "${Esc}[37m") + set(BoldRed "${Esc}[1;31m") + set(BoldGreen "${Esc}[1;32m") + set(BoldYellow "${Esc}[1;33m") + set(BoldBlue "${Esc}[1;34m") + set(BoldMagenta "${Esc}[1;35m") + set(BoldCyan "${Esc}[1;36m") + set(BoldWhite "${Esc}[1;37m") + endif() endif() diff --git a/cmake/configure_cpp_options.cmake b/cmake/configure_cpp_options.cmake index 9a6cc8a7902de8bd14d412f0ca4fc86a3bc116fc..73f8202a72d029e04d433e39f4f99d4436bdce74 100644 --- a/cmake/configure_cpp_options.cmake +++ b/cmake/configure_cpp_options.cmake @@ -18,17 +18,15 @@ set( CMAKE_BUILD_TYPE "Release" CACHE STRING "CMake build mode to use" ) set( CMAKE_CXX_STANDARD 17 CACHE STRING "C++ standard used for the build" ) set( CMAKE_CXX_EXTENSIONS FALSE CACHE BOOL "(Dis)allow using GNU extensions" ) -set( CMAKE_CXX_STANDARD_REQUIRED TRUE CACHE BOOL - "Require the specified C++ standard for the build" ) +set( CMAKE_CXX_STANDARD_REQUIRED TRUE CACHE BOOL "Require the specified C++ standard for the build" ) # Setting CMAKE_CXX_FLAGS to avoid "deprecated" warnings -set(CMAKE_CXX_FLAGS "-Wno-deprecated-declarations" ) # very basic -#set(CMAKE_CXX_FLAGS "-Wall -Werror -pedantic-errors -Wno-deprecated-declarations" ) # good enough for a quick, better check -#set(CMAKE_CXX_FLAGS "-Wall -Wextra -Werror -pedantic-errors -Wno-deprecated-declarations" ) # better for a thorough check -#set(CMAKE_CXX_FLAGS "-Wall -Wextra -Werror -pedantic-errors" ) # better for an even more severe check -#set(CMAKE_CXX_FLAGS "-Weverything -Werror -pedantic-errors" ) # not recommended, it warns for really EVERYTHING! - +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-declarations" ) # very basic +#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror -pedantic-errors -Wno-deprecated-declarations" ) # good enough for a quick, better check +#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror -pedantic-errors -Wno-deprecated-declarations" ) # better for a thorough check +#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror -pedantic-errors" ) # better for an even more severe check +#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Weverything -Werror -pedantic-errors" ) # not recommended, it warns for really EVERYTHING! # TODO: for Debug and with GCC, do we want to set the flags below by default? # set( CMAKE_BUILD_TYPE DEBUG ) -# set(CMAKE_CXX_FLAGS "-fPIC -O0 -g -gdwarf-2" ) +# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -O0 -g -gdwarf-2" ) diff --git a/documentation/.gitlab-ci.yml b/documentation/.gitlab-ci.yml index 6e4698985ffaaab280fcbbef2b24e08a1c90f8c0..f9ce56b7bf4d4e54c9b0bedbfa2f5a22cbd28ed4 100755 --- a/documentation/.gitlab-ci.yml +++ b/documentation/.gitlab-ci.yml @@ -38,6 +38,6 @@ deploying: "EOS_PATH": "/eos/project/g/geomodel/www/home" image: gitlab-registry.cern.ch/ci-tools/ci-web-deployer:latest only: - - master + - main script: - deploy-eos diff --git a/documentation/README.md b/documentation/README.md index 79c3a7c79a73ec3dbdb34bb95c888bf4e9cdc055..53683f0fa29431b8b1582064e69211fb2b25f6bc 100755 --- a/documentation/README.md +++ b/documentation/README.md @@ -1,4 +1,4 @@ -[](https://gitlab.cern.ch/GeoModelDev/documentation/commits/master) +[](https://gitlab.cern.ch/GeoModelDev/documentation/commits/main) # GeoModel - A Detector Description Toolkit for HEP experiments diff --git a/documentation/docs/components/geomodelxml/index.md b/documentation/docs/components/geomodelxml/index.md new file mode 100644 index 0000000000000000000000000000000000000000..20d05cc6565519df8f989b7d1679249be8b96af4 --- /dev/null +++ b/documentation/docs/components/geomodelxml/index.md @@ -0,0 +1,438 @@ +From [documentation written by N. Hessey](https://twiki.atlas-canada.ca/pub/AtlasCanada/ITk/gmx2geo.pdf) + +This is an initial version of the documentation, and is a work-in-progress needing in several places updates to reflect the latest status. + +# 1 Introduction + +The ATLAS software framework Athena uses GeoModel [1] as the central geometry store. The geometry is stored in a graph (or tree), and a set of objects (materials, shapes etc.) which are managed by GeoModel. The graph has a collection of “physical volumes” of some shape with dimensions and filled with a material. These can contain other physical volumes. They have names and integer identifiers, as well as transformations giving their position. These transformations can be changed during program execution, to allow for movements of detector elements and for software align- ment of components. This manual assumes familiarity with GeoModel, as well as a rudimentary knowledge of xml. +The objects and tree are built up by C++ code calling GeoModel methods. Most of ATLAS geometry is currently built up using C++ code directly, while the muon non-sensitive geometry (services, supports, magnets etc.) is built up in AGDD [2] which is an xml-based geometry description; C++ routines parse the xml and use generic code to build up the GeoModel geometry. +For studies of future Inner Tracker layouts, several geometries need to be explored. To speed these studies up, a package GeoModelXml has been written. This package contains a Document Type Definition (DTD) file, and hopefully later an xml schema. These create an xml geometry-definition- language called gmx ("GeoModel in Xml") and provides a C++ package GeoModelXml to convert the gmx file into a GeoModel tree and the required GeoModel objects. The recommended filename extension for gmx geometry description files is `.gmx`, which helps distinguish the files from other xml. + +There are several needs in Athena which are very closely linked to the geometry. These are the ATLAS Identifier scheme, the digitization process for Geant hits (“Readout Geometry”), and detector software alignment. GeoModelXml only handles the solid geometry: materials, shapes, logical volumes and physical volumes. Identifiers, Readout Geometry, and Alignment, are factored out and handled separately in other packages. The link between these and the geometry are steered in the xml: whenever a volume that is declared “sensitive” is created, two call-back routines are called: one to create a detector identifier, the other to set-up the digitisation routines to handle this volume; and whenever a volume declared “alignable” is created, a call-back routine is invoked to store the relevant information in the geometry manager for the software alignment transformations. + +After a brief back-ground on xml, this manual has three sections. The first is for people who just want to modify or develop a geometry where someone has already set-up Athena to use GeoModelXml. The next explains the C++ code to make a “Detector Manager” that uses gmx. The third is to aid code maintenance, giving an introductory overview of how the code is organised. + +## 2 Why use xml +The ATLAS Inner Detector geometry in Athena is currently defined directly in C++ code, with most (but not all) dimensions and quantities stored in the data base. The Pixel and TRT geometries are each defined in one long (a few thousand lines of code) C++ file. The SCT geometry is defined in several smaller files, with one class per type of item. The former system is difficult to maintain; the latter requires quite some effort to code new geometries. The SCT method makes something very clear though: we basically do the same thing over and over in building up geometries, giving hope of automating this with some C++ code, steered by a control file. + +Xml (extensible markup language) is very well suited to geometry description: it can store numbers, such as dimensions, as well as their meaning; it can also handle hierarchical structures (such as Inner Detector has a barrel has cylinders have staves...). It can be extended with whatever tags the user needs. These and their allowed content are defined in a “DTD” file or alternatively in a “schema” file. Standard freely available software such as Xerces-C [3] can parse the xml, checking it follows both the rules of xml and the rules given in the DTD. Insisting the xml description file follows the DTD greatly simplifies programming: the code only has to check for things that cannot be enforced in the DTD/schema. Furthermore any errors are found very early, and their position can be pin-pointed with error messages. This leads to fast development of a geometry. + +If we can find some effort to also develop code to automate handling of ATLAS identifiers, digi- tization, and alignment, one could arrive at a highly flexible Athena geometry system: no need to compile-link-run to develop layouts; just modify the xml, run, and look at the results. +For geometry versioning, the xml file(s) can be stored in the conditions data-base. Some people have stated a preference for storing them and versioning them in SVN, which could also be made to work. + +# 3 Guide to Developing a Geometry in the gmx file +## 3.1 Overview +The gmx file defines materials, shapes, logical volumes (logvols, which are a combination of a shape and a material filling it), and tranformations which place copies of the logvols in the desired position. +Dimensions can be defined in terms of parameters and arithmetic expressions involving those pa- rameters. These parameters are dealt with first, creating them with their value. A few other details are also dealt with at the start: digitization-schemes and position index names (explained later). + +The next step is very important to understand. Processing then skips everything in the file until the single `<addbranch>` tag at the end. The content of the addbranch is processed to build up the geometry in a branch of the GeoModel tree. If this content refers to other objects, those are found and processed. Similarly their children are processed, and so on iteratively until the addbranch contents are completed. So for example you can build up a large `<materials>` section and include it in all your projects. Only the materials and elements that you actually use in your geometry via the `<addbranch>` element will be created. You will not waste resources (neither memory nor cpu) during execution of Athena by having a large material file. Unused materials, shapes, logvols etc. will never be turned into GeoModel items - they can sit in the gmx ready for future use, though of course can clutter your gmx file. Note that while this means the file is processed in an apparently random order, the file must obey xml rules. These include the rule that if an attribute references another element, that element must have already been given. So the `<addbranch>` element has to come last. A logical order for the other tags would be defines, materials, shapes, logvols/assemblies, then the addbranch. However to allow flexibility in file inclusion and re-use, this is not imposed. +There are no “PhysVols” in the gmx file. Instead, each time a logvol is encountered during process- ing, a GeoPhysVol (or GeoFullPhysVol, if the logvol is alignable or sensitive) is created and added to the tree. For all tags that create GeoModel objects, the code is careful to only create one version, and use it many times. So the first time a logvol is encountered, a GeoLogVol is created followed by a Geo(Full)PhysVol which is added to the GeoModel tree. A pointer to the logvol is also stored in a list maintained by the logvol processor. This list (an STL map in C++ terms) is indexed by the logvol name. On a subsequent use of the logvol, it is found, via the name attribute, in the map and used in a Geo(Full)PhysVol, without recreating the logvol. + +Several tags use this mechanism. This is the reason why many tags have mandatory names: even if the user does not need to refer to the name, it is needed for insertion in the map. Apart from this, the names allow the user to reference items, and make the gmx more readable. +Geometries in ATLAS can be large and complicated. Different parts may be managed by differ- ent people. Furthermore, some parts may be wanted in several geometries. To help keep things maintainable, and allow re-use (especially of materials) you are recommended to split the input in several files. Flexibility above the minimum strictly necessary has been built in to the DTD to allow sensible distribution of the gmx over several files. This can be done with the standard xml mechanism: one sets up the main file (first file called) with the usual xml header, giving the DTD file; then create local entities with the names of sub-files to be included. When the parser encounters this entity (surrounded by `&` and `;`), it will switch to reading input from that file. +Look in the DTD file in the package data directory for all details of what is and is not allowed. The following sections do not attempt to cover all possibilities and restrictions, but rather give a quick start to developing good gmx files. + +## 3.2 Debugging a gmx file - gmx2geo +There are various xml checkers around, which can give a very quick check of your gmx files. However, I have not found one that easily allows multiple input files, DTDs and schemas, and they do not necessarily pin down error positions as well as possible. +Once things are more or less set up, running VP1 in Athena is a powerful tool to see if you have created what you intended. But this is rather a slow way to find you misspelt an identifier or some other minor mistake. So I have developed a standalone way of checking gmx files: a program called gmx2geo. Once installed, it takes a second or so to find and pin-point the first error in the gmx file, which is very useful and saves a lot of development time. In the absence of xml errors, it goes on to build up the full GeoModel tree, and then traverse it, printing out a very verbose list of your geometry. Not generally useful, but can be helpful for difficult problems and for debugging GeoModelXml itself. + + +### 3.2.1 + +Here we had some installation instructions, but they are completely out-of-data now... to think about how to replace. +<!-- +GeoModelXml headers and a shared library of all .o files: You can use your standard Athena install, and run make in the src directory; or (for non-Athena computers) download using svn (from svn+ssh://svn.cern.ch/reps/atlas-hessey/GeoModelXml), edit the makefile in the src directory – especially (and hopefully only) the PROG variable – and do a make in the src directory. +gmx2geo: Download with svn (from svn+ssh://svn.cern.ch/reps/atlas-hessey/gmx2geo). In the src directory edit the makefile especially the PROG definition, and do make. +Running gmx2geo +src directory, and do make. +In principle, copy the executable gmx2geo from the src directory to somewhere in your PATH, and just type +gmx2geo <filename>.gmx +In practice, you probably want to pipe it to less or send the output to a file for later browsing. +--> + +### 3.3 Basic gmx file contents + +Example of the start and end of a gmx file, with use of including materials from another file: +``` +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE geomodel SYSTEM "/path_to_GeoModelXml/trunk/src/geomodel.dtd" [ +<!ENTITY materialFile SYSTEM "materials.gmx"> <!-- Internal DTD stuff--> +]> +<!-- The xmlns attribute says un-named namespace things are gmx: --> +<geomodel name="Example to illustrate basic structure of a gmx file" + version="1.0" xmlns="http://www.nikhef.nl/\%7Er29/gmx"> +<!-- Defines etc. here --> +&materialFile; +<!-- lots more stuff building up the logvol called SCT_logvol --> +<addbranch> + <logvolref ref="SCT_logvol"/> +</addbranch> +</geomodel> +``` +This assumes that a file called materials.gmx exists in this directory too. Usually xml files access the DTD on the web with http: access. However this is disabled in the Athena version of Xerces-C used for the xml processing. This restriction is probably a good idea: for versioning, we need to store the DTD and all xml files in the data base. Loading content from the web cannot be versioned properly. So you must use the DTD in the data directory in the package. +The DTD is stored in svn in the GeoModelXml package trunk/data directory. With cmt installation, there is no trunk directory. + +### 3.4 Units + +Lengths are in mm; angles in radians; densities in g/cm3 (same as kg/m3) and internally are con- verted to be consistent with Athena units. + +### 3.5 Parameters and evaluation of numeric expressions + +For maintainability and readability, it is much better to assign a meaningful name for a number, and use the name rather than the number directly. Furthermore it is very useful to be able to derive other dimensions from a basic given one. Gmx therefore allows the definition of named parameters with a numerical value. These parameters can be used in numerical expressions to derive other numerical values. +The expressions are CLHEP-Evaluator expressions [4]. Common mathematical functions are al- lowed; e.g. the following can be useful: +``` +<var name="PI" value="acos(-1.0)"/> +``` + +The definitions are given inside `<define>` tags, and can be `<var>`, `<vector>`, or `<matrix>` values. You are recommended to make the defines all at the start of the gmx file in which they are used, or in a separate file or files to be included in the main file. To allow this, <define> sections can be distributed throughout the gmx file at the top level (i.e as direct children of the geomodel node). +All the parameters should be considered as constants (despite any suggestion from the tag name “var”). Their values are set in the order they appear in the gmx file. Thus an expression can only use previously declared parameters. <define>s are the first thing processed. This is the safest way! Xml is not a procedural language, and the xml file is not processed top to bottom (see overview section); this makes it unpredictable to use any truely “variable” parameter system. So gmx like the following is forbidden (the second `<var>` element attempts to re-use the unique xml-ID name- attribute), but in anycase would not have produced what the user presumably wanted: +For now, avoid white space after the last number in a matrix or vector list, or you will create an extra matrix or vector element. (To be fixed sometime). +``` +<defines> + <var name="InnerRad" value="100."/> +</defines> +<shapes> + <tube name="HollowTube" rmin="InnerRad" rmax="200." zhalflength="400."/> +</shapes> +<defines> + <var name="InnerRad" value="0."/> + <!-- illegal! Second occurrence of InnerRad --> +</defines>   +<shapes> + <tube name="SolidTube" rmin="InnerRad" rmax="200." zhalflength="400."/> +</shapes> +``` +would produce two identical (solid) tubes, one with a misleading name HollowTube. The last value given, 0.0 here, is the one that would be used everywhere for InnerRad, if this construct had been allowed in the DTD. +Three types of parameters can be defined: atomic constants; vectors; and matrices. Internally there are only atomic variables; a “vector” tag with name vecvar and dimension 3 creates three variables called vecvar_0, vecvar_1, vecvar_2. A matrix named m is converted to variable m_0_0 etc. with the first digit giving the row and the second giving the column; the user uses these extended names later in the gmx file to refer to the values. +Matrix and vector values must be pure numbers, separated by white space; the values are not passed through any evaluator. (Possibly in the future this could change, e.g. giving a list of semi-colon separated expressions to be evaluated.) +Example: +``` +<defines> + <var name="PI" value="acos(-1.0)"/> + <var name="TWOPI" value="2 * PI"/> + <vector name="UnitK" value="0 0 1"/> + <matrix name="twoCols4Rows" coldim="2" value="0 1 2 3 4 5 6 7"/> +</defines> +``` +You are recommended to implement some sort of namespace system for variable names, and avoid common names like xLen, to avoid clashes. E.g. precede all your variables with a three letter acronym followed by an underscore. + +### 3.6 Adding geometry branches + +The `<addbranch>` tag is where it all starts, as soon as the `<defines>` have been done. Typically the `<addbranch>` contains one or a few references to some object, say a `<logvolref>`. Processing starts at the first such reference, and creates it. If that contains children, they in turn are processed. When a logvol is first encountered, its material and shape are created (if not already created for some other logvol). +GeoModelXml allows you to chose any (valid xml ID entity) name you like for a logvol etc. in `<addbranch>`. However Athena and VP1 have conventions used with this name: they understand the names Pixel, SCT, TRT among others; and for children of SCT, Barrel, ForwardPlus, and For- wardMinus (Endcap-A = ForwardPlus) are understood. +   +### 3.7 Materials + +These follow very much the GeoModel manual description. Elements are created with name and shortname and given Z and A (atomic number and atomic weight). Materials are given a name and density (in g/cm3), and contain mass-fractions of elements and other materials. For example: +``` + <materials> <!-- Fractions are by mass --> + <element name="Hydrogen" shortname="H" Z="1" A="1.0079"/> + <element name="Carbon" shortname="C" Z="6" A="12.011"/> + <element name="Nitrogen" shortname="N" Z="7" A="14.007"/> + <element name="Oxygen" shortname="O" Z="8" A="15.999"/> + <material name="Graphite" density="2.267"> <!-- Wikipedia Carbon --> + <elementref fraction="1.0" ref="Carbon"/> + </material> + <material name="Bisphenol-A" density="1.2"> + <elementref fraction="0.03" ref="Hydrogen"/> + <elementref fraction="0.75" ref="Carbon"/> + <elementref fraction="0.10" ref="Nitrogen"/> + <elementref fraction="0.12" ref="Oxygen"/> + </material> + <material name="CyanateEster" density="1.2"> + <!-- It's a secret what they actually use --> + <materialref fraction="1.0" ref="Bisphenol-A"/> + </material> + <material name="K13D2U" density="1.820"> + <materialref fraction="0.721" ref="Graphite"/> + <materialref fraction="0.279" ref="CyanateEster"/> + </material> + </materials> +``` +### 3.8 Shapes + +All shapes available in the GeoModel manual are implemented. The tag-name and parameter at- tribute names are all lower-case, but otherwise are identical to the shape name and parameter names used in the GeoModel manual. The generictrap shape is also implemented but not yet in the Geo- Model manual. Refer to the GeoModel manual for further details of shapes. +Shapes are enclosed in a `<shape>` tag. This facilitates checking that a reference is indeed a reference to a shape item. +Shapes can be combined into “boolean” shapes with `<union>` (addition of two shapes), `<subtraction>` (removal of second shape from first), and `<intersection>` (only the volume common to both shapes) elements. The content of all these is always two shaperefs separated by a transformation applied to the second shaperef. If the transformation is empty, it acts as the identity transformation. +Example including a dice with a hole from corner to diagonally opposite corner: + +``` +<shapes> + <box name="BoxShape" xhalflength="50." yhalflength="70." zhalflength="90."/> + <box name="Cube" xhalflength="5." yhalflength="5." zhalflength="5."/> + <tube name="Tube" rmin="0" rmax="1." zhalflength="10."/> + <subtraction name="DiceForANecklace"> + <shaperef ref="Cube"/> + <transformation name="Rotate45Deg"> + <rotation xcos="sqrt(2) / 2" ycos="sqrt(2) / 2" angle="PI/4"/> + </transformation> + <shaperef ref="Tube"/> + </subtraction> +</shapes> +``` + +### 3.9 Logical volumes + +The main stuff of gmx. Logical volumes (logvols) are a combination of a shape and a material, via attributes that give a reference to these things. They have a name so they can be referred to. +Unlike in GeoModel, logvols can contain other logvols. This works since the C++ GeoModelXml package positions and copies logvols into physvols, which can indeed contain other physvols. +In the following example, first a simple Box item is created. Then a large box is created to contain three copies of this box, spread along the z-axis, using `<transform>` elements. The Box is referenced via `<logvolref>` elements: + +``` +<box name="BoxShape" xhalflength="50" yhalflength="50" + zhalflength="50"/> +<box name="BigBox" xhalflength="1000" yhalflength="1000" + zhalflength="1000"/> +<logvol name="Box" material="K13D2U" shape="BoxShape" + alignable="false"/> +<logvol name="ThreeBoxes" shape="BigBox" material="N2"> + <transform> + <transformation> + <translation z="-500"/> + </transformation> + <logvolref ref="Box"/> + </transform> + <logvolref ref="Box"/> + <transform> + <transformation> + <translation z="+500"/> + </transformation> + <logvolref ref="Box"/>   + </transform> +</logvol> +``` + +Logvols by default are not alignable, which is generally suitable for services and support material, and lead to a GeoPhysVol element being created. Logvols that have sensitive detector children are often made alignable by setting the alignable attribute to true. Alignable logvols get turned into GeoFullPhysVols. These store their full position, allowing them to be moved around efficiently with software alignment of sensitive detector elements. +Another attribute of a logvol is “sensitive”. By default, logvols are insensitive material. If the sen- sitive attribute is given, it must reference a `<digitizationscheme>` element. These elements contain information such as number of strips and strip dimensions needed for digitization of Geant hits. +The child logvols of a logvol can be entered as new logvols, assemblies, transforms and ref-versions of these. See also the multicopy tag. + +### 3.10 Assemblies + +Assemblies are a way of collecting a group of logvols. The element content is the same as for logvols, and they can be alignable; however they cannot be sensitive. They can be manipulated as a whole (e.g. transformed) just like a logvol. The advantage of assemblies over logvols is that they need no material and dimensions specified. This avoids having to invent some non-existent shape with all its dimensions which is big enough to envelop all its content, yet without clashing with neighbouring volumes. They are converted by GEO2G4 into Geant4 G4Assembly items. +They can be included in logvols, and referred to by `<assemblyref>` tags.In the following gmx snippet, two “PetalFaces” are combined to make a petal: +``` + <assembly name="Petal" alignable="true"> + <transform name="NearFace"> + <transformation name="PlacePetalFaceNear"> + <translation z="-ISE_SensorZOffset"/> + </transformation> + <assemblyref ref="PetalFace"/> + </transform> + <transform name="FarFace"> + <transformation name="PlacePetalFaceFar"> + <translation z="ISE_SensorZOffset"/> + <rotation xcos="1." angle="PI"/> + </transformation> + <assemblyref ref="PetalFace"/> + </transform> + </assembly> +``` + +Internally, GeoModel recognises something as an assembly if its material is "special::Ether". GeoModelXml makes a single logvol called AssemblyLV containing special::Ether. All assemblies share this same logvol. This information can be useful when viewing with VP1, both to understand why such a logvol has been created without you asking for it, and to help manipulate viewing assemblies to make them visible or invisible. An unfortunate consequence of this is that many items in the tree end up called AssemblyLV making debugging harder. + +### 3.11 Moving things around: Transformations and Transforms + + +Objects (logvols, assemblies, and shapes when combined into boolean shapes) need to be moved around. This is accomplished by applying transformations, which consist of a sequence of trans- lations, rotations, and scalings in any order. First these are combined into a single `HepGeom::Transform3d`, which is used to create a GeoTransform (or GeoAlignableTransform if the transform, transformation, and moved object are alignable). +The contents of a transformation are `<translation>`, `<rotation>`, and `<scaling>` elements. These have attributes to specify the transformation: x, y, z for translations; three direction-cosines specifying an axis of rotation through the origin xcos, ycos, zcos and the amount of the rotation in radians angle for rotations; and scale factors in each direction x, y, z for scalings (negative values give a parity transformation). All these attributes are set up to give an identity transformation: all 0 for translations and rotations; all 1 for scalings. So in general the user has to specify only a small subset of the attributes. +Generally supplying several simple successive transformations is easier to read and debug than trying to combine them yourself into a minimum number of transforms in the gmx file; they are combined internally into a single transformation, so there is no memory or cpu cost during Athena running by doing this. +A logvol or assembly can be moved by placing it in a <transform> element, along with the item to be moved (or a reference to such an item). See the Assembly section above for an example of this use. To avoid confusion between transform and transformation tags, think of transform! as a command to apply a transformation to an object. +The other uses of transformations are in building up boolean shapes (see the shapes section) and in `<multicopy>` elements (see next section). + +### 3.12 Short-cuts for Multiple Copies + +Xml is not a procedural language, and so does not have loop constructs, which tend to be very useful when making geometries in C++. It is not easy (nor wise) to implement loops in xml: look at the discussion above on why parameters are constants and think about what difficulties arise if you try to make a loop with a parameter depending on the loop counter, in an xml processor that does not process the xml serially from top to bottom. This lack of loop constructs tends to lead to quite some repetition in gmx files. +Some of this can be avoided using a `<multicopy>` element. Suppose you want several copies of a logvol to be added at regular translations (e.g. strip silicon sensors on a stave) or rotations (e.g. petals in a wheel). One could make an assembly with a transform object for each copy, incrementing the transformation in each transform. `<multicopy>` elements act as an abbreviation for this. One gives the transformation followed by the object to be transformed, and an attribute n giving the number of copies required. The first copy will be placed as-is (i.e. ”transformation to the power 0”); the second with the transformation applied once; and each subsequent copy has the transformation applied once more (“transformation to the power copy-number”). +Example to make a wheel of petals, assuming a “petal-pair” has been made consisting of two petals in a castellated layout: +``` + <assembly name="Wheel"> + <multicopy name="AddPetalPairsToWheel" n="16" > + <transformation name="PlacePetalPairsToWheel"> + <rotation zcos="1." angle="2*PI/16"/> + </transformation> + <assemblyref ref="PetalPair"/> + </multicopy> +</assembly> +``` +Note that the copy-number of each physvol added runs from 0 to n-1 every time the multicopy is encountered; i.e. in multicopy the copy number is automatically zeroed at the start of inserting the copies. This is almost always what is wanted. So there is no zeroid attribute. +Another common occurrence is to make several copies of an object at an irregular spacing, for example wheels in an endcap. multicopy has an attribute loopvar for this. If the loopvar attribute is given, its value must be the name of a vector defined in the defines section. Transformations can use the vector name as if it were a scalar value. For successive copies, the vector name will be set equal to successive values of the vector. E.g. to place wheels in an endcap: +``` + <defines> + ... + <vector name="WheelPos" value="1400. 1600. 2000. 2500. 3000"/> + ... + </defines> +... + <assembly name="Endcap"> + <multicopy name="AddWheelsToEndcap" n="5" loopvar="WheelPos"> + <transformation name="PlaceWheel"> + <translation z="WheelPos"/> <!-- WheelPos is set to WheelPos_0, WheelPos_1, ... WheelPos_4 in turn --> + </transformation> + <assemblyref ref="Wheel"/> + </multicopy> +</assembly> +``` + +### 3.13 Positional Indices +There are several concepts of “neighbours” and “order” which are not strictly part of the solid geom- etry, but are closely related to it, and very useful. In principle one could create some sophisticated package which recognised from the juxtapositions of volumes which ones are neighbours, and what order a track passes through them. Such code would be difficult to write and probably would not cope well with all geometries. Especially as some of these concepts are subjective and approximate, and anyway need to be backward compatible with previous Athena software, in particular with the ATLAS identifier scheme. Hence in practice this needs steering by the user. +GeoModelXml generically allows for such schemes. The user can create as many positional indices as desired, with whatever names seem useful. In practice, these should mesh with the detector manager: so for the strip inner tracker, should provide barrel_endcap, layer_wheel, eta_module, phi_module, and side indices so an SCT_ID can be produced. +The user creates a list of indices in a `<positionindex>` element, using the `<addindex>` element for each: +``` +<positionindex> + <addindex name="section"/> + ... + <addindex name="sensor_phi"/> +</positionindex> +``` + +The names and values of the indexes are passed to GmxInterfaces in a map, with name as key and the index-value as value. +Each index is associated to a formula in an <index> element. These formulae can appear in logvols, assemblies, and multicopies. They are dynamic: each time a formula is encountered, any previous stored string is over-written. It is changed as soon as the <index> element is encountered. Evaluation of all formulae occurs only and always when an alignable transform or a sensitive logvol is encountered. The resulting values are passed to the user via the addAlignable() or addSensor() methods of the GmxInterface class. The user is thus able to calculate ATLAS Identifiers etc. and store them in a Detector Manager for example. + +The formulae are CLHEP evaluator expressions. They can use the defined var, vector, and matrix elements (see `<defines>`). In addition, and in general much more usefully, they can use the copy- numbers of all their parent Geo(Full)PhysVols. Each time such a physvol is made, it is stored with a copy number (GeoIdentifierTag) in the GeoModel graph. This integer is incremented each time a logvol is copied into a physvol. The user can reset this copy-number to zero whenever appropriate by setting logvolref and assemblyref elements attribute zeroid="true". For example, suppose you have a stave volume used in three successive barrel cylinders. Each time you start a new cylinder, you probably want to add the `zeroid=“true”` to the first stave in the cylinder. + +During processing of the `<addbranch>` element and its daughters, one descends through several levels of physvols. E.g. the strip barrel maybe be the top level (level 0); the cylinders maybe be the next down (level 1); then staves, stave-faces, modules, sensors (level = 5). To access these copy- numbers, the user must create a special vector called CNL (“Copy-Number Level”) in a <defines> element and give it a length at least as big as the biggest depth (so 6 elements in the example given). Typically just set each element to 0. There is no choice about the name; it is hard-wired in the code: + +``` +<defines> + ... + <vector name="CNL" value="0 0 0 0 0 0"/>   + ... +</defines> +``` +The formulae for position indexes can then use the variables CNL_0, ..., CNL_5 (or more if you make the vector longer). These have dynamic values, i.e. they are an exception to the rule. Inter- nally, they are given the appropriate value at the time of use, by looking at the copy-numbers of the alignable/sensitive volume and those of all its ancestors. +Suppose you want the phi-index of a sensitive-detector element to be equal to its stave copy-number. Then one would use something like: +``` +... +<digitizationscheme name="barrelSSDetector" + params="nRows = 4; nStrips = 1240; ..."/> +... +<positionindex> + ... + <addindex name="phi_module"/> + ... +</positionindex> +... +<logvol name="barrelShortStripSensor" sensitive="barrelSSDetector"> + <index name="phi_module" value="CNL_2"/> + <!-- CNL_2 is the stave copy number--> +</logvol> +... +``` +This example has a very simple formula; in practice sometimes the formula may need to be much more complicated. The formula has to be entered in one line, unlike in C++. Sometimes the conditional operators available in the CLHEP evaluator are useful. If you want different formulae according to whether CNL_0 is 0 or 1, try something like +``` +(CNL_0 == 0) * CNL_5 + (CNL_0 == 1) * (64 - CNL_5) +``` +to have an index increasing in one case and decreasing in the other. +Other indexes can be used in the formula, by using the positionalindex name. The values are always calculated in the order that the names are given in the position index element. So if you want to use the value of layer_disk when calculating the side position-index, make sure the <addindex> for layer_disk precedes that for side. +One can also use dimensions such as a barrel radius to decide a layer index. Yes, some things are much easier in C++ than xml. + +### 3.14 Sensitive Volumes + +Silicon sensors, muon tubes etc. are sensitive to the passage of high energy particles. They need special treatment in Geant4 so that energy deposits (“Geant Hits”) can be registered, and then these deposits processed through electronics simulations to be converted into digital output (“digitiza- tion”). To allow this, these sensitive volumes are built up into the “Readout Geometry”. These things are not handled in GeoModelXml, but they are allowed for with an attribute “sensitive”. This can only be given for a logvol (i.e. not for assemblies or multicopies). The value of the attribute is a reference to a `<sensortype>`. +Each time a logvol is encountered with a ‘sensitive’ attribute, a GeoFullPhysVol (as opposed to a GeoPhysVol) will be created. First a call-back is made to the user’s sensitiveId function which has to return a 32-bit integer. This integer is stored as the GeoIdentifierTag of the GeoFullPhysVol. Then a call-back is made to the addSensor() method of the GmxInterface, with parameters including the digitization-scheme name, a map of positionalindex names and values, and a pointer to the GeoFullPhysVol. The user’s addSensor() usually should register the physvol as sensitive in the Detector Manager, storing pointers to it and associating a unique identifier (the upper part of a full ATLAS-identifier) to it. +In detail: for the inner tracker simulation, the sensitiveId should be the Simulation Identifier. These are defined in InDetSimEvent/SiHit.h and SiHitIdHelper.h. Use the position index values and the GetHelper()->buildHitId method. This then becomes the G4 volume copy number via Geo2G4. A (currently private) copy of Geo2G4 is needed if you want to use assemblies; the standard Geo2G4 recalculates copy numbers in the case assemblies are used. G4Hits are processed in the package InnerDetector/InDetG4/SCT_G4_SD. A private copy of this uses the hit-volume’s copy number directly, assuming it is the required ATLAS Simulation Identifier (Not the ATLAS Offline Identifier!). +See the section on position indexes for example code. + +### 3.15 Alignment + +The actual ATLAS detector has its sensitive detector elements positioned slightly displaced from the ideal locations, and furthermore these elements move around with thermal expansion etc. To account for these changing positions, the data base stores the actual positions as corrections to the ideal positions. These corrections are often derived by looking at the data in a process known as software alignment. The GeoModel geometry needs to allow for these displacements for analysis of real events. +Essentially in a running detector, each sensitive element is alignable at level-0. Then each support structure (e.g. module, cyclinder, barrel-section) is also made alignable at subsequent levels. This hierarchy allows displacements of large components to be followed rapidly and accurately, while the individual sensitive detectors can be aligned less frequently, once enough statistics have been built up. +Note that simulation is carried out with detectors in their ideal positions. It has proved difficult to apply displacements in Geant4 because they tend to lead to clashes between volumes. So for developing layout designs for future detectors, alignment is not really needed. But for long term use, including once any detector has been built, we need the option to include alignment. Hence alignment is allowed for in GeoModelXml (but not tested, and unlikely to be tested for some time), with a similar procedure involving a call-back routine addAlignable() which is a member of the GmxInterface class. The parameters include the level as described in the previous paragraph, pointers to both the transformation and physvol, and the same map of index-names and values as passed to the addSensor() routines. +The alignment system requires a transformation to place the alignable physvol, even if the transformation is the identity (which will be modified by the actual small offsets). Hence it is convenient to make a transform alignable with an alignable attribute, thus ensuring both elements are present. By default (in the absence of this attribute), the transform will not produce anything alignable. Each time an alignable transform is encountered, the addAlignable() method is called. The alignment level is set to the value of the alignable attribute, which must evaluate to zero or a positive integer. +To be alignable, the transformation must be a GeoAlignableTransform and the physvol must be a GeoFullPhysVol as opposed to the simpler GeoTransform and GeoPhysVol versions that are produced by default. Since these can be defined outside a transform and could (at least in principle) first be encountered in a non-alignable case, they also need to be flagged as alignable. The alignable attribute in this case though only needs to be set to “true”, which is sufficient to trigger the creation of the correct type of GeoModel object. Transformations, logvols, assemblies, and multicopies all have an alignable attribute, default value false, which can be set true to make an alignable version. +To summarise: For now, you can ignore alignable. But when the time comes to use alignment, all three of transform, transformation, and object (logvol, assembly or multicopy) need the alignable attribute set. The transform sets the level, the other two are set to true. + +### 4 Guide to setting up a GeoModel detector-tool to use a gmx file + +This section is once again completely out-of-date and needs a complete rewrite. + +<!-- +In order to make use of GeoModelXml, you need to make a GeoModel detector tool (i.e. GeoModelXml is not itself an Athena tool, but becomes part of the GeoModel Detector Tool when you use it). The following sections give the current method, with for an example the SCT_SLHC_GeoModel package as the GeoModel Detector Tool. These instructions were valid round about December 2013 and work with Athena version 17.3.4. + +### 4.1 Packages needed +The following packages from the ATLAS SVN repositories are required: + • Standard version InnerDetector/InDetExample/InDetSLHC_Example + • Version 00-00-74 DetectorDescription/GeoModel/GeoModelKernel + • Version 00-05-07 graphics/VP1/VP1Utils + • Version 00-06-12 graphics/VP1/VP1HEPVis + • Version 00-01-05 Simulation/G4Utilities/Geo2G4 Currently (April 2014) the above Geo2G4 version needs a small but important change to give hits correctly; and SCT_G4_SD needs major changes. Ask the author for the fixes. The following packages from the atlas-hessey user repositories are also required: • GeoModelXml + +ATLAS Project Document No: +None +• SCT_SLHC_GeoModel• Version 00-03-20 InnerDetector/InDetG4/SCT_G4_SD • GmxITkStripLoI• SiHitMapper +Page: 19 of 21 Rev. No.: C +   +The last four are only needed for LoI strip layout, but are a useful starting point for any other layout or detector. The intention is eventually to move these to the standard ATLAS SVN region, simplifying life. +4.2 Helper Scripts and Preparation of Athena +To help users get going, the scripts I use to install the packages are made available at Instructions: + 1. Create a new work area (e.g. mkdir athena/17.3.12; cd athena/17.3.12). + 2. Copy the three files initialise, getPackages, and buildAll from my web pages at [6] into it (e.g. wget www.nikhef.nl/ r29/upgrade/gmx/initialise) + 3. The file initialise is used to setup your Athena environment. Amend it to suit your local environment. It might need quite some changes depending on your local Athena installation. Then source it (don’t execute it). + 4. Getting the packages: make the getPackages file user-executable (chmod u+x getPack- ages). Edit it to reflect your directory structure and your lxplus user-name. Use kinit <lxplus-user-name> to avoid having to type in your password over and over again. Then execute it. Watch for errors; it should download all needed Athena packages from both the atlas-offline repository (atlasoff) and the atlas-hessey repository. It also downloads some further small files from my web pages at [6] and moves these to the appropriate directories in packages downloaded from the atlasoff repository. + 5. Building the packages: make the file buildAll user-executable. Execute it, saving the output into a log file. Check the log-file: each package should build successfully, with some message like “All OK”. +The initialise file is then sourced each time you start a new terminal in which you want to work on your geometry. But do not run getPackages again: it may overwrite any fixes you made, and you might lose them. +I am interested to hear suggestions for improving these scripts so they work on many platforms. +4.3 Running VP1 to view and debug your geometry +Use the InDetSLHC_Example package to run Athena with VP1. Descend into InnerDetector/In- DetExample/InDetSLHC_Example/run. Edit jobOptions_display_SLHC and amend the top-level .gmx file path to suit your environment. +From then on, you can run VP1 with (remembering to “source initialise” if you have a new xterm): + +ATLAS Project Document No: Page: 20 of 21 None Rev. No.: C +athena -l ERROR jobOptions_display_SLHC.py > athena.log +If all is well, VP1 should fire up. Select "Geometry Studies" in the main window. Select the "Geo" tab on the left. Check "Other unrecognised volumes" or your detector name. Voila: your geometry is displayed. +4.4 Implementing a GeoModel Detector Factory with GeoModelXml +Included in the above installation is the package SCT_SLHC_GeoModel from my SVN area. This already has everything you need to get running for ITk strip geometries. +However, if you want to make a new subsystem, or modify some other subsystem (pixels, beam- pipe, beam monitor, ...) here is a very brief guide. +You need to build a GeoModel detector tool. Look at my version of the SCT_SLHC_GeoModel package tool. It has a class called SCT_SLHC_DetectorTool in a .h and .cxx file. You need some- thing like this as the starting point for your geometry. You also need the SCT_ComponentFactory, SCT_GeoModelAthenaComps, and components directory stuff (these are all standard things for Athena tools). +Then you need to make a GeoModel detector factory, as described in the GeoModel manual [1]. In this factory, you need the following: +... +#include "GeoModelXml/Gmx2Geo.h" +#include "GeoModelXml/GmxInterface.h" +... +// In the create method of your Detector Factory, add the following +// at the appropriate place +void XXX_DetectorFactory::create(GeoPhysVol *world){ + string filename("myGeometry.gmx") // Change name to your top-level .gmx + // file, or of course better still + // pass it as a python parameter + ... // All sorts as required in the GeoModel manual + GmxInterface gmxInterface; + Gmx2Geo gmx2Geo(filename, world, gmxInterface); + ... // More stuff as required in the GeoModel manual +   +// +// +// +// +// +// + Add the tree-top to the detector manager. This also makes it + appear as SCT in VP1. It is probably the last (most recently + added) thing in the world PV so loop from the back looking for + our subdetector name. +unsigned int nChildren = world->getNChildVols(); + +ATLAS Project Document No: Page: 21 of 21 None Rev. No.: C + for (int iChild = nChildren - 1; iChild; --iChild) { + if (world->getNameOfChildVol(iChild) == "SCT") { + // The * converts from a ConstPVLink to a reference to + // a GeoVPhysVol; the & takes its address. + m_detectorManager->addTreeTop(&*world->getChildVol(iChild)); + break; +} } +This will create an instance of a Gmx2Geo object which will process the file (in the constructor), and add volumes to “world” as instructed. It also adds your detector to the detector manager. There are some naming conventions to follow, which allow VP1 to pick-up your detector. +4.4.1 GmxInterface +The GmxInterface class is a base class implementing four call-back routines. It interfaces the Ge- oModelXml package to your detector factory tool. The methods are addSensorType, sensorId, addSensor, and addAlignable. The first is called each time a <digitizationscheme> element is en- countered. The second two are called each time a <logvol> with its ’sensitive’ attribute set is encountered. The last is called each time a <transform> with alignable attribute is encountered. The parameter list includes pointers to GeoFullPhysVols, GeoAlignableTransforms, and a map of positional index names and their values. The intention is that the user over-rides the default methods with methods using the detector manager to build up the readout geometry and alignment schemes. The default methods simply print out debugging information. +Probably it is best to first set up a geometry without any alignable or sensitive parameters, and develop it using VP1. Then deal with sensitive volumes. Then finally deal with alignable volumes. This can be done using the default GmxInterface methods to check the input; then finally switch to your over-ridden versions of these methods. +--> + +### References +[1] Joe Boudreau, GeoModel Manual, http://atlas.web.cern.ch/Atlas/GROUPS/ DATABASE/detector_description/Geometry%20Kernel%20Classes.doc + +[2] AGDD web pages Cannotfindthem + +[3] Xerces-C web pages https://xerces.apache.org/xerces-c/ + +[4] CLHEP web pages http://wwwasd.web.cern.ch/wwwasd/lhc++/clhep/index.html#docu + +[5] Virtual Point-1 display package web pages http://atlas-vp1.web.cern.ch/atlas-vp1/index.php + +[6] http://www.nikhef.nl/~r29/upgrade/gmx diff --git a/documentation/docs/dev/docs-contrib.md b/documentation/docs/dev/docs-contrib.md index d84346a63b619acb93590721540539c4bfbcbdd6..737ca37802b29f3bec00f232668c09b26e822fa7 100644 --- a/documentation/docs/dev/docs-contrib.md +++ b/documentation/docs/dev/docs-contrib.md @@ -33,7 +33,7 @@ Thus, if you only want to update the documentation, you can merely: 1. fork the GeoModel repository 2. edit the documentation files you want to update 3. push your changes -4. create a Merge Request to get your changes merged into the GeoModel `master` branch +4. create a Merge Request to get your changes merged into the GeoModel `main` branch However, if you want to preview your changes on your machine---and we recommend that---, you need to install `MkDocs` on your machine. diff --git a/documentation/docs/dev/index.md b/documentation/docs/dev/index.md index 7124fbfbb5e2deeb75bedeea0e3c92a5271fff33..6eaf95c36c5f2d8975af5731c02a36cd39051129 100644 --- a/documentation/docs/dev/index.md +++ b/documentation/docs/dev/index.md @@ -50,6 +50,10 @@ echo 'export PATH="/opt/homebrew/opt/qt@5/bin:$PATH"' >> ~/.zshrc After having installed `qt` with brew, and having run the `echo` command stated above, you should either open a new shell or run `source ~/.zshrc` in order to get the `qt` in the `PATH`. +!!! warning + If you have both Qt5 and Qt6 installed through the `brew` package managers on your macOS machine, you will probably get errors while building GeoModelVisualization. `brew` in fact installs the Qt6 and Qt5 packages as `qt` and `qt@5` respectively. When compiling GeoModelVisualization, CMake does find the correct version of Qt, while later the linker fails to do that and complain. To fix that, just remove Qt6 with `brew remove qt`. This is a temporary solution, until we move the GeoModel code to Qt6. + + !!! warning Before building the GeoModel libraries from source, please check if you have old versions of them installed on your system and remove them. @@ -66,7 +70,11 @@ echo 'export PATH="/opt/homebrew/opt/qt@5/bin:$PATH"' >> ~/.zshrc On Ubuntu, you can install all the needed third-party dependencies by using the built-in `apt` package manager: ```bash -sudo apt-get update -qq && sudo apt-get install -y -qq git cmake wget unzip build-essential freeglut3-dev libboost-all-dev qtbase5-dev libeigen3-dev libxerces-c-dev libsqlite3-dev + +sudo add-apt-repository ppa:kaktusjoe/geomodel +sudo apt update + +sudo apt install git cmake wget unzip build-essential nlohmann-json3-dev libsoqt-bb-dev libxerces-c-dev libeigen3-dev geant4-dev libsqlite3-dev zlib1g-dev libhdf5-dev qtbase5-dev libhepmc3-dev pythia-dev ``` ### Linux/Fedora @@ -169,7 +177,7 @@ wget http://cern.ch/atlas-software-dist-eos/externals/Simage/Coin3D-simage-2c958 unzip Coin3D-simage-2c958a61ea8b.zip cd Coin3D-simage-2c958a61ea8b ./configure --prefix=$PWD/../install -wget -O cc7.patch https://gitlab.cern.ch/atlas/atlasexternals/-/raw/master/External/Simage/patches/libpng_centos7.patch?inline=false +wget -O cc7.patch https://gitlab.cern.ch/atlas/atlasexternals/-/raw/main/External/Simage/patches/libpng_centos7.patch?inline=false patch -p1 < cc7.patch make -j4 make install @@ -185,7 +193,7 @@ Now, you should build Coin3D (the 3D graphics engine) and SoQt (the glue package ```bash # Build Coin3D wget https://geomodel.web.cern.ch/sources/coin-5a97506-20210210.zip -O coin.zip -unzip coin.zip; mv coin-master coin +unzip coin.zip; mv coin-* coin mkdir build_coin cd build_coin cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=Release -DCOIN_BUILD_TESTS=0 -DCMAKE_CXX_FLAGS=-Wno-deprecated-declarations ../coin @@ -207,7 +215,7 @@ cd .. ## Quick instructions - Build everything -With these instructions you will build the whole software stack for GeoModel development. The GeoModel libraries will be built from the HEAD version of the 'master' branch. If something does not compile, please [let the developers' team know](../about/contacts.md). +With these instructions you will build the whole software stack for GeoModel development. The GeoModel libraries will be built from the HEAD version of the 'main' branch. If something does not compile, please [let the developers' team know](../about/contacts.md). With these instructions, you will build: `GeoModelCore`, `GeoModelIO`, `GeoModelTools`, `GeoModelVisualization` (a.k.a., `gmex`). diff --git a/documentation/docs/dev/troubleshooting.md b/documentation/docs/dev/troubleshooting.md index a8bc361b2c633239aa37b20d846d38e29f2edfc6..65218e92ad17cfcbb5cac35f78b798daf6686d30 100644 --- a/documentation/docs/dev/troubleshooting.md +++ b/documentation/docs/dev/troubleshooting.md @@ -1,5 +1,27 @@ # Troubleshooting + +## GeoModelVisualization (GMEX) + +### "OpenGL context could not be created" + +If, after starting `gmex`, you get a window that tells you that was not possible to open an "OpenGL context", that can happen for two reasons: + +* try to restart your machine. Seriously! :-) Sometimes, after updates to the graphical packages (those can happen behind the scene, without you to notice them), the system needs to be restarted. I experienced that personally: `gmex` was failing to start, when I was trying a new version of our 3D engine, Coin3D, and I was trying to find for the cause in the code of Coin3D itself... But then my OpenGL-accelerated terminal emulator, Alacritty, had stopped working as well; and that gave me a hint that something global was happening... So, I Googled, and I found a suggestion to resart the machine to get the graphics drivers sync between each others. Try that first, it can help! ;-) +* your OpenGL installation / support is not correct / fully-installed. In that case, you should look for instructions to install proper OpenGL support on your system. + +### GMEX crashes on the latest Ubuntu + +The GeoModelExplorer (GMEX) application appears to crash when run on the latest version of the Ubuntu "Wayland" window manager. + +The problem is that the SoQt/Coin third-party packages we use in GMEX have not been ported to work to the latest Wayland yet. As far as we know, all applications that use the Coin/SoQt graphics layers as their graphics interface crash on the latest Wayland. + +The Coin3D community is aware of the problem but there are no fixes, yet. + +Therefore, we strongly suggest to use the alternative X11 window manager when running GEMX (or all other SoQt/Coin3D-based applications) on Ubuntu, for the time being. + + + ## Packages ### macOS / Homebrew diff --git a/documentation/docs/fullsimlight/fsl/index.md b/documentation/docs/fullsimlight/fsl/index.md index 333815bfafee233f3278df9da9ce896d676598b0..8e842685904ee679a8fdf86a8749e53354b55be7 100644 --- a/documentation/docs/fullsimlight/fsl/index.md +++ b/documentation/docs/fullsimlight/fsl/index.md @@ -70,7 +70,7 @@ To use Pythia one can select one of the pre-customized options which are - higgs - minbias -Details about the default options can be found in the `PythiaPrimaryGeneratorAction` [class](https://gitlab.cern.ch/GeoModelDev/GeoModel/-/blob/master/FullSimLight/src/PythiaPrimaryGeneratorAction.cc). +Details about the default options can be found in the `PythiaPrimaryGeneratorAction` [class](https://gitlab.cern.ch/GeoModelDev/GeoModel/-/blob/main/FullSimLight/src/PythiaPrimaryGeneratorAction.cc). Alternatively one can also provide a custom Pythia configuration input file. ### 3. HepMC3 File diff --git a/documentation/docs/fullsimlight/fullsimlight/index.md b/documentation/docs/fullsimlight/fullsimlight/index.md index 66660bc8563b5e42d4519136a56cb5ce4df71409..013fa86fb12ba9b8fc8219e286f29e119a0ad5a3 100644 --- a/documentation/docs/fullsimlight/fullsimlight/index.md +++ b/documentation/docs/fullsimlight/fullsimlight/index.md @@ -14,7 +14,7 @@ For instructions on how to build FullSimLight, please refer to the [Build FullSi ### Geometry: -The supported geometry formats are SQLite (.db), GDML (.gdml) and plugins that build from scratch a GeoModel geometry (.dylib/.so). An example of geometry plugins can be found in the [GeoModelExamples folder](https://gitlab.cern.ch/GeoModelDev/GeoModel/-/tree/master/GeoModelExamples/KitchenSinkPlugin). +The supported geometry formats are SQLite (.db), GDML (.gdml) and plugins that build from scratch a GeoModel geometry (.dylib/.so). An example of geometry plugins can be found in the [GeoModelExamples folder](https://gitlab.cern.ch/GeoModelDev/GeoModel/-/tree/main/GeoModelExamples/KitchenSinkPlugin). Use the -g flag to specify the name of the input geometry file. ### ATLAS Geometry Files: diff --git a/documentation/docs/fullsimlight/plugins/index.md b/documentation/docs/fullsimlight/plugins/index.md index a5ba6c985083a058702aefbc29f956bd09b25664..8d72c03f925d7ff61bafc9e31cb71fc79ab9313d 100644 --- a/documentation/docs/fullsimlight/plugins/index.md +++ b/documentation/docs/fullsimlight/plugins/index.md @@ -13,36 +13,36 @@ For a description of the available example plugins look at the following section ##Geometry plugins -Some geometry example plugins are available at the [GeoModelATLAS](https://gitlab.cern.ch/atlas/geomodelatlas/GeoModelATLAS) repository, under the [Example Plugins](https://gitlab.cern.ch/atlas/geomodelatlas/GeoModelATLAS/-/tree/master/ExamplePlugins) folder. The `ToyGeometryPlugin` and the `AccordionPlugin` are the right examples to start with. +Some geometry example plugins are available at the [GeoModelATLAS](https://gitlab.cern.ch/atlas/geomodelatlas/GeoModelATLAS) repository, under the [Example Plugins](https://gitlab.cern.ch/atlas/geomodelatlas/GeoModelATLAS/-/tree/main/ExamplePlugins) folder. The `ToyGeometryPlugin` and the `AccordionPlugin` are the right examples to start with. ##User Actions plugins -You can find some example user actions plugins under the FullSimLight/Plugins folder. In particular we provide a DummyUserAction plugin available [here](https://gitlab.cern.ch/GeoModelDev/GeoModel/-/tree/master/FullSimLight/Plugins/Examples/UserActionPlugins) and a [Hits plugin](https://gitlab.cern.ch/GeoModelDev/GeoModel/-/tree/master/FullSimLight/Plugins/HitsPlugin) and a [Track plugin](https://gitlab.cern.ch/GeoModelDev/GeoModel/-/tree/master/FullSimLight/Plugins/TracksPlugin). +You can find some example user actions plugins under the FullSimLight/Plugins folder. In particular we provide a DummyUserAction plugin available [here](https://gitlab.cern.ch/GeoModelDev/GeoModel/-/tree/main/FullSimLight/Plugins/Examples/UserActionPlugins) and a [Hits plugin](https://gitlab.cern.ch/GeoModelDev/GeoModel/-/tree/main/FullSimLight/Plugins/HitsPlugin) and a [Track plugin](https://gitlab.cern.ch/GeoModelDev/GeoModel/-/tree/main/FullSimLight/Plugins/TracksPlugin). ###Hits Plugin -The [Hits plugin](https://gitlab.cern.ch/GeoModelDev/GeoModel/-/tree/master/FullSimLight/Plugins/HitsPlugin) implements both `G4UserSteppingAction` and `G4UserEventAction`. At each step the particle position (x,y,z coordinates) is saved and at the end of the event the hits are saved into a HDF5 output file. The same file can be in a second step visualized in `gmex`. +The [Hits plugin](https://gitlab.cern.ch/GeoModelDev/GeoModel/-/tree/main/FullSimLight/Plugins/HitsPlugin) implements both `G4UserSteppingAction` and `G4UserEventAction`. At each step the particle position (x,y,z coordinates) is saved and at the end of the event the hits are saved into a HDF5 output file. The same file can be in a second step visualized in `gmex`. ###Tracks Plugin -The [Tracks Plugin](https://gitlab.cern.ch/GeoModelDev/GeoModel/-/tree/master/FullSimLight/Plugins/TracksPlugin) implements `G4UserRunAction`, `G4UserEventAction`, `G4UserSteppingAction`, `G4UserTrackingAction`. For each track at each step the position is recorded and mapped into a map. At the end of the event the information is saved into a HDF5 output file (the default name is Tracks_data.h5). The tracks file data can be in a second step visualized in `gmex`. +The [Tracks Plugin](https://gitlab.cern.ch/GeoModelDev/GeoModel/-/tree/main/FullSimLight/Plugins/TracksPlugin) implements `G4UserRunAction`, `G4UserEventAction`, `G4UserSteppingAction`, `G4UserTrackingAction`. For each track at each step the position is recorded and mapped into a map. At the end of the event the information is saved into a HDF5 output file (the default name is Tracks_data.h5). The tracks file data can be in a second step visualized in `gmex`. ##Sensitive Detectors plugins -One sensitive detectors example plugin is provided [here](https://gitlab.cern.ch/GeoModelDev/GeoModel/-/blob/master/FullSimLight/Plugins/Examples/SensitiveDetectorPlugins/SDPlugin/src/SDPlugin.cxx). It's a dummy plugin that serves the purpose of showing how to implement the corresponding FullSimLight abstract interface. +One sensitive detectors example plugin is provided [here](https://gitlab.cern.ch/GeoModelDev/GeoModel/-/blob/main/FullSimLight/Plugins/Examples/SensitiveDetectorPlugins/SDPlugin/src/SDPlugin.cxx). It's a dummy plugin that serves the purpose of showing how to implement the corresponding FullSimLight abstract interface. ##Magnetic Field plugins -An example Magnetic field plugin can be found [here](https://gitlab.cern.ch/GeoModelDev/GeoModel/-/tree/master/FullSimLight/Plugins/Examples/MagneticFieldPlugins/UniformMagneticFieldPlugin). It implements a uniform magnetic field. +An example Magnetic field plugin can be found [here](https://gitlab.cern.ch/GeoModelDev/GeoModel/-/tree/main/FullSimLight/Plugins/Examples/MagneticFieldPlugins/UniformMagneticFieldPlugin). It implements a uniform magnetic field. An ATLAS specific Magnetic Field plugin is also available in the [ATLAS Extensions](https://gitlab.cern.ch/atlas/geomodelatlas/ATLASExtensions) repository. Please refer to the ATLAS Extensions page for further info. ##Physics list plugins -A physics list plugin example is available [here](https://gitlab.cern.ch/GeoModelDev/GeoModel/-/tree/master/FullSimLight/Plugins/Examples/PhysicsListPlugins/FSLTestPhysListPlugins). It implements a custom physics list that is based on the standard `FTFP_BERT`, adding the `G4OpticalPhysics` process. +A physics list plugin example is available [here](https://gitlab.cern.ch/GeoModelDev/GeoModel/-/tree/main/FullSimLight/Plugins/Examples/PhysicsListPlugins/FSLTestPhysListPlugins). It implements a custom physics list that is based on the standard `FTFP_BERT`, adding the `G4OpticalPhysics` process. ##Event Generators plugins -An Event generator example plugin is available [here](https://gitlab.cern.ch/GeoModelDev/GeoModel/-/tree/master/FullSimLight/Plugins/Examples/EventGeneratorPlugins/FSLExamplePrimaryGeneratorPlugin). +An Event generator example plugin is available [here](https://gitlab.cern.ch/GeoModelDev/GeoModel/-/tree/main/FullSimLight/Plugins/Examples/EventGeneratorPlugins/FSLExamplePrimaryGeneratorPlugin). It shows how to customize the use of the `G4ParticleGun`and set some properties as the particle type, name, energy, position, polarization, and momentum direction. ## How to write a plugin: the Hits Plugin example diff --git a/documentation/docs/start/install.md b/documentation/docs/start/install.md index 807d27ee92f14e29bb76f706c0a4e27add718cbe..b30c47468c612a5554019b2952967d0bd67cf4e2 100644 --- a/documentation/docs/start/install.md +++ b/documentation/docs/start/install.md @@ -42,6 +42,13 @@ sudo apt install geomodel-visualization-dev If you have outdated packages, these commands will replace those packages with the most recent version. +!!! warning + + The GeoModelExplorer (GMEX) application appears to crash when run on the latest version of the Ubuntu "Wayland" window manager. The problem is that the SoQt/Coin third-party packages we use in GMEX have not been ported to work to the latest Wayland yet. As far as we know, all applications that use the Coin/SoQt graphics layers as their graphics interface crash on the latest Wayland. The Coin3D community is aware of the problem but there are no fixes, yet. + + We strongly suggest to use the alternative X11 window manager when running GEMX (or all other SoQt/Coin3D-based applications) on Ubuntu, for the time being. + + ## macOS On macOS, we use the [Homebrew package manager](http://brew.sh) to handle and install the GeoModel packages. If you don't have Homebrew installed on your machine, you should first install it by following the instructions on the Homebrew website: <http://brew.sh>. Please be attentive to any instructions printed after the installation procedure; there might be environment variables to set. diff --git a/documentation/requirements.txt b/documentation/requirements.txt index edc09f55d055a709a9d412a99ddc5ebed38339f5..6b83f1f97453bf8af1652780150e0424e75c5879 100644 --- a/documentation/requirements.txt +++ b/documentation/requirements.txt @@ -17,6 +17,7 @@ mkdocs-material==6.1.6 mkdocs-material-extensions==1.0.1 mkdocs-minify-plugin==0.3.0 nltk==3.5 +packaging Pygments==2.7.2 pymdown-extensions==8.0.1 python-dateutil==2.8.1