Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • clantz2/zdclg
  • shengy3/zdclg
  • dmaclea2/zdclg
3 results
Show changes
Commits on Source (24)
Showing with 138024 additions and 226 deletions
......@@ -9,6 +9,7 @@
using namespace std;
int main(int argc, char *argv[]){
float xRange, zRange;
if(argc == 0) return 0;
TFile *f = new TFile( argv[1] );
if(f->IsZombie()){
......@@ -21,17 +22,24 @@ int main(int argc, char *argv[]){
if(name.find(".") != string::npos) name.erase( name.find_last_of(".") );
TTree *t = (TTree*)f->Get("lightGuide");
double x,z;
vector<double> *x=0,*z=0;
t->SetBranchAddress("X",&x);
t->SetBranchAddress("Z",&z);
xRange = (argc > 2) ? atof( argv[2] ) : 40.;
zRange = (argc > 3) ? atof( argv[3] ) : 80.;
TCanvas *c = new TCanvas("Data","Data",1280,720);
TH2D *h = new TH2D("eff","Relative Efficiency",44,-82,82,21,-42.875,42.875);
TH2D *h = new TH2D("eff","Relative Efficiency",44,-1*zRange/2.,zRange/2.,21,-1*xRange/2.,xRange/2.);
//h->SetCanExtend(0);
int nEvents = t->GetEntries();
for(int ev = 0; ev < nEvents; ev++){
t->GetEntry(ev);
h->Fill(z,x);
int nPoints = x->size();
for(int i = 0; i < nPoints; i++){
h->Fill(z->at(i),x->at(i));
}
}
gStyle->SetOptStat(0);
......
......@@ -19,14 +19,6 @@ endif()
list(APPEND CMAKE_PREFIX_PATH $ENV{ROOTSYS})
find_package (ROOT REQUIRED)
include(${ROOT_USE_FILE})
#----------------------------------------------------------------------------
# Find CADMesh
find_package(cadmesh)
include_directories(${CADMESH_INCLUDE_DIRS})
if(CADMESH_INCLUDE_DIRS)
add_definitions(-DCADMESH)
endif()
#----------------------------------------------------------------------------
# Setup Geant4 include directories and compile definitions
#
......@@ -44,11 +36,16 @@ file(GLOB headers ${PROJECT_SOURCE_DIR}/include/*.hh)
# Add the executable, and link it to the Geant4 libraries
#
add_executable(lightGuide lightGuide.cc ${sources} ${headers})
target_link_libraries(lightGuide ${Geant4_LIBRARIES} ${ROOT_LIBRARIES} cadmesh )
target_link_libraries(lightGuide ${Geant4_LIBRARIES} ${ROOT_LIBRARIES})
add_executable(plotHisto ${DEPENDENCIES} Analysis/plotHisto.cc)
TARGET_LINK_LIBRARIES(plotHisto ${ROOT_LIBRARIES})
#----------------------------------------------------------------------------
#Add Compiler flags
#
add_definitions(-Wno-shadow)
#----------------------------------------------------------------------------
# Copy all scripts to the build directory, i.e. the directory in which we
# build lightGuide. This is so that we can run the executable directly because it
......
MIT License
Copyright (c) 2024 srlund2
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
......@@ -12,8 +12,6 @@ This simulation is based on OpNovice and OpNovice2
- CERN ROOT
- CADMesh is required to read CAD models (i.e. stl, step), but is optional for compiling. Avaialble at https://github.com/christopherpoole/CADMesh
#### main()
define Random Number Engine, initial seed, CAD input and GDML output
......@@ -57,6 +55,7 @@ CAD models can be imported and positioned via
/lightGuide/model/translate
/lightGuide/model/translatePMT
```
The models must be in ASCII STL format in the current implementation.
And the optical properties of a sub volume of G4Air which the light guide sits in can be configured via
```
......
#----- Set the beam energy profile -----
/gps/particle opticalphoton
/gps/ene/type Gauss
/gps/ene/mono 3.4 eV
/gps/ene/sigma 1 eV
/gps/ene/mono 4.75 eV
/gps/ene/sigma 10 eV
/gps/ene/min 1.9 eV
/gps/ene/max 7.6 eV
/gps/ene/gradient -200 MeV
/gps/polarization 0 0 0
#----- Set the beam geometry -----
# Circular beam source. Simulates a single fiber optic
/gps/pos/type Beam
/gps/pos/shape Circle
#/gps/pos/type Beam
#/gps/pos/shape Circle
#/gps/pos/radius 0.75 mm
/gps/pos/radius 102 mm
#/gps/pos/radius 1.5 mm
#/gps/pos/sigma_r 0.002 mm
# Rectangular plane for infinite resolution
#/gps/pos/type Plane
#/gps/pos/shape Rectangle
#/gps/pos/halfx 40 mm
#/gps/pos/halfy 68 mm
/gps/pos/type Plane
/gps/pos/shape Rectangle
/gps/pos/halfx 40 mm
/gps/pos/halfy 68 mm
# the incident surface is in the x-z plane just below the gas
/gps/pos/rot1 1 0 0
......
......@@ -2,8 +2,9 @@
/lightGuide/worldVolume 0.25 0.25 0.25 m
/lightGuide/envelope 89.75 113. 165. mm
#/lightGuide/model/nSegmentsX 1
#/lightGuide/model/nSegmentsZ 1
/lightGuide/model/PMTDiameter 53 mm
/lightGuide/model/nSegmentsX 1
/lightGuide/model/nSegmentsZ 1
......@@ -11,51 +12,27 @@
#If no model is selected, the program will default to a
#simplified version of the 2018 testbeam light guide
#/lightGuide/model/CADmodel ../models/LightGuide2018TB.stl
#/lightGuide/model/rotate 0 90 0
#/lightGuide/model/translate 0 -250 200 mm
#/lightGuide/model/translatePMT 0 339 0 mm
/lightGuide/model/CADmodel ../models/run2.stl
/lightGuide/model/translate 200 -125 0 mm
/lightGuide/model/translatePMT 0 -74.5 0 mm
#/lightGuide/model/CADmodel ../models/Winston_cone.stl
#/lightGuide/model/rotate 0 0 90
#/lightGuide/model/translate 0 -111 0 mm
#/lightGuide/model/translatePMT 0 339 0 mm
#/lightGuide/model/CADmodel ../models/LightGuide2007BigPMT.stl
#/lightGuide/model/rotate 0 -90 0
#/lightGuide/model/translate 0 -250 -200 mm
#/lightGuide/model/translatePMT 0 131 0 mm
#/lightGuide/model/CADmodel ../models/EMprototype.stl
#/lightGuide/model/translate 0 0 0 mm
#/lightGuide/model/translatePMT 0 -74.5 0 mm
#/lightGuide/model/CADmodel ../models/LightGuide2007SmallPMT.stl
#/lightGuide/model/rotate 0 -90 0
#/lightGuide/model/translate 0 -250 -200 mm
#/lightGuide/model/translatePMT 0 131 0 mm
#/lightGuide/model/CADmodel ../models/run2.stl
#/lightGuide/model/rotate 0 0 0
#/lightGuide/model/translate 200 -250 0 mm
#/lightGuide/model/translatePMT 0 -119 0 mm
#/lightGuide/model/CADmodel ../models/EMprototypeSingle.stl
#/lightGuide/model/translate 175.25 -27.75 -8 mm
#/lightGuide/model/translatePMT 0 0 0 mm
#/lightGuide/model/CADmodel ../models/run3wc.stl
#/lightGuide/model/CADmodel ../models/2020WC.stl
#/lightGuide/model/rotate 0 0 90
#/lightGuide/model/translate 0 -319 0 mm
#/lightGuide/model/translatePMT 0 -119 0 mm
#/lightGuide/model/CADmodel ../models/YuvalCone.stl
#/lightGuide/model/translate 200 -136.75 0 mm
#/lightGuide/model/translatePMT 0 -136.5 0 mm
#/lightGuide/model/PMTDiameter 170
#/lightGuide/model/CADmodel ../models/YuvalHad.stl
#/lightGuide/model/translate 0 -319 0 mm
#/lightGuide/model/translatePMT 0 -136.5 0 mm
#/lightGuide/model/PMTDiameter 170
#----- Set surface properties of the light guide -----
/lightGuide/surface/Model unified
/lightGuide/surface/Type dielectric_metal
/lightGuide/surface/Finish ground
#/lightGuide/surface/Model unified
#/lightGuide/surface/Type dielectric_metal
#/lightGuide/surface/Finish ground
#/lightGuide/surface/SigmaAlpha .1
#/lightGuide/surface/Property SPECULARLOBECONSTANT 0.000002 .4 0.000008 .4
#/lightGuide/surface/Property SPECULARSPIKECONSTANT 0.000002 .1 0.000008 .1
......
/gps/hist/type theta
/gps/hist/point 0.000000 0.000000
/gps/hist/point 0.008726 0.001677
/gps/hist/point 0.026179 0.002438
/gps/hist/point 0.043632 0.002966
/gps/hist/point 0.061085 0.003407
/gps/hist/point 0.078538 0.003771
/gps/hist/point 0.095990 0.004110
/gps/hist/point 0.113443 0.004415
/gps/hist/point 0.130896 0.004724
/gps/hist/point 0.148349 0.005010
/gps/hist/point 0.165801 0.005293
/gps/hist/point 0.183254 0.005592
/gps/hist/point 0.200707 0.005862
/gps/hist/point 0.218160 0.006130
/gps/hist/point 0.235613 0.006412
/gps/hist/point 0.253065 0.006682
/gps/hist/point 0.270518 0.006950
/gps/hist/point 0.287971 0.007234
/gps/hist/point 0.305424 0.007515
/gps/hist/point 0.322876 0.007781
/gps/hist/point 0.340329 0.008063
/gps/hist/point 0.357782 0.008323
/gps/hist/point 0.375235 0.008598
/gps/hist/point 0.392687 0.008907
/gps/hist/point 0.410140 0.009175
/gps/hist/point 0.427593 0.009454
/gps/hist/point 0.445046 0.009775
/gps/hist/point 0.462499 0.010074
/gps/hist/point 0.479951 0.010385
/gps/hist/point 0.497404 0.010707
/gps/hist/point 0.514857 0.011049
/gps/hist/point 0.532310 0.011366
/gps/hist/point 0.549762 0.011748
/gps/hist/point 0.567215 0.012158
/gps/hist/point 0.584668 0.012550
/gps/hist/point 0.602121 0.012953
/gps/hist/point 0.619574 0.013384
/gps/hist/point 0.637026 0.013836
/gps/hist/point 0.654479 0.014333
/gps/hist/point 0.671932 0.014900
/gps/hist/point 0.689385 0.015575
/gps/hist/point 0.706837 0.016303
/gps/hist/point 0.724290 0.017249
/gps/hist/point 0.741743 0.018648
/gps/hist/point 0.759196 0.019849
/gps/hist/point 0.776649 0.020756
/gps/hist/point 0.794101 0.021327
/gps/hist/point 0.811554 0.019696
/gps/hist/point 0.829007 0.018203
/gps/hist/point 0.846460 0.017120
/gps/hist/point 0.863912 0.016291
/gps/hist/point 0.881365 0.015641
/gps/hist/point 0.898818 0.015079
/gps/hist/point 0.916271 0.014629
/gps/hist/point 0.933724 0.014212
/gps/hist/point 0.951176 0.013883
/gps/hist/point 0.968629 0.013545
/gps/hist/point 0.986082 0.013284
/gps/hist/point 1.003535 0.013057
/gps/hist/point 1.020988 0.012847
/gps/hist/point 1.038440 0.012644
/gps/hist/point 1.055893 0.012443
/gps/hist/point 1.073346 0.012321
/gps/hist/point 1.090799 0.012159
/gps/hist/point 1.108251 0.012022
/gps/hist/point 1.125704 0.011891
/gps/hist/point 1.143157 0.011784
/gps/hist/point 1.160610 0.011684
/gps/hist/point 1.178063 0.011600
/gps/hist/point 1.195515 0.011499
/gps/hist/point 1.212968 0.011423
/gps/hist/point 1.230421 0.011358
/gps/hist/point 1.247874 0.011273
/gps/hist/point 1.265326 0.011216
/gps/hist/point 1.282779 0.011145
/gps/hist/point 1.300232 0.011114
/gps/hist/point 1.317685 0.011054
/gps/hist/point 1.335137 0.011028
/gps/hist/point 1.352590 0.010988
/gps/hist/point 1.370043 0.010938
/gps/hist/point 1.387496 0.010915
/gps/hist/point 1.404949 0.010911
/gps/hist/point 1.422401 0.010852
/gps/hist/point 1.439854 0.010845
/gps/hist/point 1.457307 0.010834
/gps/hist/point 1.474760 0.010807
/gps/hist/point 1.492212 0.010819
/gps/hist/point 1.509665 0.010799
/gps/hist/point 1.527118 0.010811
/gps/hist/point 1.544571 0.009312
/gps/hist/point 1.562024 0.008725
/gps/hist/point 1.570700 0.000000
#/gps/hist/point -0.007400 0.000000
/gps/hist/point 0.000000 0.000059
/gps/hist/point 0.007400 0.000338
/gps/hist/point 0.014800 0.000512
/gps/hist/point 0.022200 0.000687
/gps/hist/point 0.029600 0.000990
/gps/hist/point 0.037000 0.001121
/gps/hist/point 0.044400 0.001404
/gps/hist/point 0.051800 0.001575
/gps/hist/point 0.059200 0.001921
/gps/hist/point 0.066600 0.002071
/gps/hist/point 0.074000 0.002209
/gps/hist/point 0.081400 0.002370
/gps/hist/point 0.088800 0.002663
/gps/hist/point 0.096200 0.002832
/gps/hist/point 0.103600 0.003022
/gps/hist/point 0.111000 0.003347
/gps/hist/point 0.118400 0.003500
/gps/hist/point 0.125800 0.003817
/gps/hist/point 0.133200 0.003972
/gps/hist/point 0.140600 0.004145
/gps/hist/point 0.148000 0.004303
/gps/hist/point 0.155400 0.004621
/gps/hist/point 0.162800 0.004762
/gps/hist/point 0.170200 0.005010
/gps/hist/point 0.177600 0.005308
/gps/hist/point 0.185000 0.005465
/gps/hist/point 0.192400 0.005574
/gps/hist/point 0.199800 0.005896
/gps/hist/point 0.207200 0.006192
/gps/hist/point 0.214600 0.006292
/gps/hist/point 0.222000 0.006516
/gps/hist/point 0.229400 0.006742
/gps/hist/point 0.236800 0.006942
/gps/hist/point 0.244200 0.007175
/gps/hist/point 0.251600 0.007442
/gps/hist/point 0.259000 0.007549
/gps/hist/point 0.266400 0.007859
/gps/hist/point 0.273800 0.007951
/gps/hist/point 0.281200 0.008102
/gps/hist/point 0.288600 0.008663
/gps/hist/point 0.296000 0.008789
/gps/hist/point 0.303400 0.009103
/gps/hist/point 0.310800 0.009285
/gps/hist/point 0.318200 0.009436
/gps/hist/point 0.325600 0.009630
/gps/hist/point 0.333000 0.009931
/gps/hist/point 0.340400 0.010256
/gps/hist/point 0.347800 0.010362
/gps/hist/point 0.355200 0.010797
/gps/hist/point 0.362600 0.010825
/gps/hist/point 0.370000 0.011403
/gps/hist/point 0.377400 0.011606
/gps/hist/point 0.384800 0.011730
/gps/hist/point 0.392200 0.011980
/gps/hist/point 0.399600 0.012238
/gps/hist/point 0.407000 0.012208
/gps/hist/point 0.414400 0.012737
/gps/hist/point 0.421800 0.013022
/gps/hist/point 0.429200 0.013560
/gps/hist/point 0.436600 0.013393
/gps/hist/point 0.444000 0.013733
/gps/hist/point 0.451400 0.014151
/gps/hist/point 0.458800 0.014394
/gps/hist/point 0.466200 0.014743
/gps/hist/point 0.473600 0.015354
/gps/hist/point 0.481000 0.015463
/gps/hist/point 0.488400 0.015805
/gps/hist/point 0.495800 0.016047
/gps/hist/point 0.503200 0.016040
/gps/hist/point 0.510600 0.016432
/gps/hist/point 0.518000 0.016911
/gps/hist/point 0.525400 0.017092
/gps/hist/point 0.532800 0.017341
/gps/hist/point 0.540200 0.017891
/gps/hist/point 0.547600 0.018050
/gps/hist/point 0.555000 0.018850
/gps/hist/point 0.562400 0.019253
/gps/hist/point 0.569800 0.019231
/gps/hist/point 0.577200 0.019886
/gps/hist/point 0.584600 0.020413
/gps/hist/point 0.592000 0.020505
/gps/hist/point 0.599400 0.021237
/gps/hist/point 0.606800 0.021726
/gps/hist/point 0.614200 0.022311
/gps/hist/point 0.621600 0.022637
/gps/hist/point 0.629000 0.023515
/gps/hist/point 0.636400 0.024492
/gps/hist/point 0.643800 0.025049
/gps/hist/point 0.651200 0.025821
/gps/hist/point 0.658600 0.026996
/gps/hist/point 0.666000 0.028316
/gps/hist/point 0.673400 0.007106
/gps/hist/point 0.680800 0.000000
/gps/hist/point 0.688200 0.000000
/gps/hist/point 0.695600 0.000000
/gps/hist/point 0.703000 0.000000
/gps/hist/point 0.710400 0.000000
/gps/hist/point 0.717800 0.000000
/gps/hist/point 0.725200 0.000000
# #OLD HIST.MAC
# /gps/hist/point 0.000000 0.000000
# /gps/hist/point 0.008726 0.001677
# /gps/hist/point 0.026179 0.002438
# /gps/hist/point 0.043632 0.002966
# /gps/hist/point 0.061085 0.003407
# /gps/hist/point 0.078538 0.003771
# /gps/hist/point 0.095990 0.004110
# /gps/hist/point 0.113443 0.004415
# /gps/hist/point 0.130896 0.004724
# /gps/hist/point 0.148349 0.005010
# /gps/hist/point 0.165801 0.005293
# /gps/hist/point 0.183254 0.005592
# /gps/hist/point 0.200707 0.005862
# /gps/hist/point 0.218160 0.006130
# /gps/hist/point 0.235613 0.006412
# /gps/hist/point 0.253065 0.006682
# /gps/hist/point 0.270518 0.006950
# /gps/hist/point 0.287971 0.007234
# /gps/hist/point 0.305424 0.007515
# /gps/hist/point 0.322876 0.007781
# /gps/hist/point 0.340329 0.008063
# /gps/hist/point 0.357782 0.008323
# /gps/hist/point 0.375235 0.008598
# /gps/hist/point 0.392687 0.008907
# /gps/hist/point 0.410140 0.009175
# /gps/hist/point 0.427593 0.009454
# /gps/hist/point 0.445046 0.009775
# /gps/hist/point 0.462499 0.010074
# /gps/hist/point 0.479951 0.010385
# /gps/hist/point 0.497404 0.010707
# /gps/hist/point 0.514857 0.011049
# /gps/hist/point 0.532310 0.011366
# /gps/hist/point 0.549762 0.011748
# /gps/hist/point 0.567215 0.012158
# /gps/hist/point 0.584668 0.012550
# /gps/hist/point 0.602121 0.012953
# /gps/hist/point 0.619574 0.013384
# /gps/hist/point 0.637026 0.013836
# /gps/hist/point 0.654479 0.014333
# /gps/hist/point 0.671932 0.014900
# /gps/hist/point 0.689385 0.015575
# /gps/hist/point 0.706837 0.016303
# /gps/hist/point 0.724290 0.017249
# /gps/hist/point 0.741743 0.018648
# /gps/hist/point 0.759196 0.019849
# /gps/hist/point 0.776649 0.020756
# /gps/hist/point 0.794101 0.021327
# /gps/hist/point 0.811554 0.019696
# /gps/hist/point 0.829007 0.018203
# /gps/hist/point 0.846460 0.017120
# /gps/hist/point 0.863912 0.016291
# /gps/hist/point 0.881365 0.015641
# /gps/hist/point 0.898818 0.015079
# /gps/hist/point 0.916271 0.014629
# /gps/hist/point 0.933724 0.014212
# /gps/hist/point 0.951176 0.013883
# /gps/hist/point 0.968629 0.013545
# /gps/hist/point 0.986082 0.013284
# /gps/hist/point 1.003535 0.013057
# /gps/hist/point 1.020988 0.012847
# /gps/hist/point 1.038440 0.012644
# /gps/hist/point 1.055893 0.012443
# /gps/hist/point 1.073346 0.012321
# /gps/hist/point 1.090799 0.012159
# /gps/hist/point 1.108251 0.012022
# /gps/hist/point 1.125704 0.011891
# /gps/hist/point 1.143157 0.011784
# /gps/hist/point 1.160610 0.011684
# /gps/hist/point 1.178063 0.011600
# /gps/hist/point 1.195515 0.011499
# /gps/hist/point 1.212968 0.011423
# /gps/hist/point 1.230421 0.011358
# /gps/hist/point 1.247874 0.011273
# /gps/hist/point 1.265326 0.011216
# /gps/hist/point 1.282779 0.011145
# /gps/hist/point 1.300232 0.011114
# /gps/hist/point 1.317685 0.011054
# /gps/hist/point 1.335137 0.011028
# /gps/hist/point 1.352590 0.010988
# /gps/hist/point 1.370043 0.010938
# /gps/hist/point 1.387496 0.010915
# /gps/hist/point 1.404949 0.010911
# /gps/hist/point 1.422401 0.010852
# /gps/hist/point 1.439854 0.010845
# /gps/hist/point 1.457307 0.010834
# /gps/hist/point 1.474760 0.010807
# /gps/hist/point 1.492212 0.010819
# /gps/hist/point 1.509665 0.010799
# /gps/hist/point 1.527118 0.010811
# /gps/hist/point 1.544571 0.009312
# /gps/hist/point 1.562024 0.008725
# /gps/hist/point 1.570700 0.000000
......@@ -35,7 +35,6 @@
#define ASCIIPrimaryGenerator_h 1
#include "G4VPrimaryGenerator.hh"
#include "lgAnalysis.hh"
#include <fstream>
#include <vector>
......
// The MIT License (MIT)
//
// Copyright (c) 2011-2020 Christopher M. Poole <mail@christopherpoole.net>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// CADMESH - Load CAD files into Geant4 quickly and easily.
//
// Read all about it at: https://github.com/christopherpoole/CADMesh
//
// Basic usage:
//
// #include "CADMesh.hh" // This file.
// ...
// auto mesh = CADMesh::TessellatedMesh::FromSTL("mesh.stl");
// G4VSolid* solid = mesh->GetSolid();
// ...
//
// !! THIS FILE HAS BEEN AUTOMATICALLY GENERATED. DON'T EDIT IT DIRECTLY. !!
#pragma once
class BuiltInReader;
class CADMeshTemplate;
class Mesh;
class STLReader;
class ASSIMPReader;
class PLYReader;
class FileTypes;
class OBJReader;
class Exceptions;
class TetrahedralMesh;
class Reader;
class Lexer;
class LexerMacros;
class TessellatedMesh;
#include "G4String.hh"
#include <algorithm>
#include <map>
namespace CADMesh {
namespace File {
enum Type {
Unknown,
PLY,
STL,
DAE,
OBJ,
TET,
OFF,
};
static std::map<Type, G4String> Extension = {
{Unknown, "unknown"}, {PLY, "ply"}, {STL, "stl"}, {DAE, "dae"},
{OBJ, "obj"}, {TET, "tet"}, {OFF, "off"}};
static std::map<Type, G4String> TypeString = {
{Unknown, "UNKNOWN"}, {PLY, "PLY"}, {STL, "STL"}, {DAE, "DAE"},
{OBJ, "OBJ"}, {TET, "TET"}, {OFF, "OFF"}};
static std::map<Type, G4String> TypeName = {
{Unknown, "Unknown File Format"}, {PLY, "Stanford Triangle Format (PLY)"},
{STL, "Stereolithography (STL)"}, {DAE, "COLLADA (DAE)"},
{OBJ, "Wavefront (OBJ)"}, {TET, "TetGet (TET)"},
{OFF, "Object File Format (OFF)"}};
Type TypeFromExtension(G4String extension);
Type TypeFromName(G4String name);
}
}
#include "G4ThreeVector.hh"
#include "G4TriangularFacet.hh"
#include <memory>
#include <vector>
namespace CADMesh {
typedef std::vector<G4ThreeVector> Points;
typedef std::vector<G4TriangularFacet *> Triangles;
class Mesh {
public:
Mesh(Points points, Triangles triangles, G4String name = "");
static std::shared_ptr<Mesh> New(Points points, Triangles triangles,
G4String name = "");
static std::shared_ptr<Mesh> New(Triangles triangles, G4String name = "");
static std::shared_ptr<Mesh> New(std::shared_ptr<Mesh> mesh,
G4String name = "");
public:
G4String GetName();
Points GetPoints();
Triangles GetTriangles();
G4bool IsValidForNavigation();
private:
G4String name_ = "";
Points points_;
Triangles triangles_;
};
typedef std::vector<std::shared_ptr<Mesh>> Meshes;
}
namespace CADMesh {
namespace File {
class Reader {
public:
Reader(G4String reader_name);
~Reader();
virtual G4bool Read(G4String filepath) = 0;
virtual G4bool CanRead(Type file_type) = 0;
public:
G4String GetName();
std::shared_ptr<Mesh> GetMesh();
std::shared_ptr<Mesh> GetMesh(size_t index);
std::shared_ptr<Mesh> GetMesh(G4String name, G4bool exact = true);
size_t GetNumberOfMeshes();
Meshes GetMeshes();
protected:
size_t AddMesh(std::shared_ptr<Mesh> mesh);
void SetMeshes(Meshes meshs);
private:
Meshes meshes_;
G4String name_ = "";
};
}
}
#include <iostream>
#include <string>
namespace CADMesh {
namespace File {
struct Token {
std::string name;
bool operator==(Token other) { return name == other.name; };
bool operator!=(Token other) { return name != other.name; };
};
static Token ErrorToken{"ErrorToken"};
static Token EnfOfFileToken{"EndOfFileToken"};
static Token ParentToken{"Parent"};
static Token WordToken{"Word"};
static Token NumberToken{"Number"};
static Token ThreeVectorToken{"ThreeVector"};
static Token VertexToken{"Vertex"};
static Token VerticesToken{"Vertices"};
static Token FacetToken{"Facet"};
static Token LineToken{"Line"};
static Token NormalToken{"Normal"};
static Token TextureToken{"Texture"};
static Token SolidToken{"Solid"};
static Token ObjectToken{"Object"};
static Token CommentToken{"Comment"};
static Token BlankLineToken{"BlankLine"};
struct Item {
Token token;
size_t position;
size_t line;
std::string value;
std::string error;
Item *parent;
std::vector<Item> children;
};
typedef std::vector<Item> Items;
typedef Items::iterator ItemsIterator;
class Lexer;
struct State {
virtual State *operator()(Lexer *) const = 0;
};
struct __FinalState : public State {
State *operator()(Lexer *) const { return nullptr; }
};
class Lexer {
public:
Lexer(std::string filepath, State *initial_state = nullptr);
public:
std::string String();
void Run(State *initial_state, size_t lines = 0);
Items GetItems();
void Backup();
void BackupTo(int position);
std::string Next();
std::string Peek();
void Skip();
Item *ThisIsA(Token token, std::string error = "");
Item *StartOfA(Token token, std::string error = "");
Item *EndOfA(Token token, std::string error = "");
Item *MaybeEndOfA(Token token, std::string error = "");
bool OneOf(std::string possibles);
bool ManyOf(std::string possibles);
bool Until(std::string match);
bool MatchExactly(std::string match);
bool OneDigit();
bool ManyDigits();
bool OneLetter();
bool ManyLetters();
bool ManyCharacters();
bool Integer();
bool Float();
bool Number();
bool SkipWhiteSpace();
bool SkipLineBreak();
bool SkipLineBreaks();
bool SkipLine();
State *Error(std::string message);
State *LastError();
bool TestState(State *state);
bool IsDryRun();
void PrintMessage(std::string name, std::string message);
void PrintItem(Item item);
size_t LineNumber();
private:
State *state_;
Item *parent_item_ = nullptr;
Items items_;
std::string input_;
size_t position_ = 0;
size_t start_ = 0;
size_t width_ = 1;
size_t line_ = 1;
size_t end_line_ = 0;
bool dry_run_ = false;
int depth_ = 0;
std::string last_error_ = "";
};
}
}
#ifdef USE_CADMESH_ASSIMP_READER
#include "assimp/Importer.hpp"
#include "assimp/postprocess.h"
#include "assimp/scene.h"
namespace CADMesh {
namespace File {
class ASSIMPReader : public File::Reader {
public:
ASSIMPReader();
~ASSIMPReader();
public:
G4bool Read(G4String filepath);
G4bool CanRead(Type file_type);
private:
Assimp::Importer *importer_;
};
std::shared_ptr<ASSIMPReader> ASSIMP();
}
}
#endif
namespace CADMesh {
namespace File {
class BuiltInReader : public Reader {
public:
BuiltInReader() : Reader("BuiltInReader"){};
public:
G4bool Read(G4String filepath);
G4bool CanRead(File::Type file_type);
};
std::shared_ptr<BuiltInReader> BuiltIn();
}
}
#ifndef CADMESH_DEFAULT_READER
#define CADMESH_DEFAULT_READER BuiltIn
#endif
#include "G4AssemblyVolume.hh"
#include "G4LogicalVolume.hh"
#include "G4Material.hh"
#include "G4TessellatedSolid.hh"
#include "G4Tet.hh"
#include "G4UIcommand.hh"
namespace CADMesh {
template <typename T> class CADMeshTemplate {
public:
CADMeshTemplate();
CADMeshTemplate(G4String file_name);
CADMeshTemplate(G4String file_name, File::Type file_type);
CADMeshTemplate(std::shared_ptr<File::Reader> reader);
CADMeshTemplate(G4String file_name, std::shared_ptr<File::Reader> reader);
CADMeshTemplate(G4String file_name, File::Type file_type,
std::shared_ptr<File::Reader> reader);
static std::shared_ptr<T> From(G4String file_name);
static std::shared_ptr<T> From(G4String file_name,
std::shared_ptr<File::Reader> reader);
static std::shared_ptr<T> FromPLY(G4String file_name);
static std::shared_ptr<T> FromPLY(G4String file_name,
std::shared_ptr<File::Reader> reader);
static std::shared_ptr<T> FromSTL(G4String file_name);
static std::shared_ptr<T> FromSTL(G4String file_name,
std::shared_ptr<File::Reader> reader);
static std::shared_ptr<T> FromOBJ(G4String file_name);
static std::shared_ptr<T> FromOBJ(G4String file_name,
std::shared_ptr<File::Reader> reader);
~CADMeshTemplate();
public:
virtual G4VSolid *GetSolid() = 0;
virtual G4VSolid *GetSolid(G4int index) = 0;
virtual G4VSolid *GetSolid(G4String name, G4bool exact = true) = 0;
virtual std::vector<G4VSolid *> GetSolids() = 0;
virtual G4AssemblyVolume *GetAssembly() = 0;
bool IsValidForNavigation();
public:
G4String GetFileName();
File::Type GetFileType();
void SetVerbose(G4int verbose);
G4int GetVerbose();
void SetScale(G4double scale);
G4double GetScale();
void SetOffset(G4double x, G4double y, G4double z);
void SetOffset(G4ThreeVector offset);
G4ThreeVector GetOffset();
protected:
G4String file_name_;
File::Type file_type_;
G4int verbose_;
G4double scale_;
G4ThreeVector offset_;
G4AssemblyVolume *assembly_ = nullptr;
std::shared_ptr<File::Reader> reader_ = nullptr;
};
}
#include "globals.hh"
namespace CADMesh {
namespace Exceptions {
void FileNotFound(G4String origin, G4String filepath);
void LexerError(G4String origin, G4String message);
void ParserError(G4String origin, G4String message);
void ReaderCantReadError(G4String origin, File::Type file_type,
G4String filepath);
void MeshNotFound(G4String origin, size_t index);
void MeshNotFound(G4String origin, G4String name);
}
}
namespace CADMesh {
class TessellatedMesh : public CADMeshTemplate<TessellatedMesh> {
using CADMeshTemplate::CADMeshTemplate;
public:
G4VSolid *GetSolid();
G4VSolid *GetSolid(G4int index);
G4VSolid *GetSolid(G4String name, G4bool exact = true);
std::vector<G4VSolid *> GetSolids();
G4TessellatedSolid *GetTessellatedSolid();
G4TessellatedSolid *GetTessellatedSolid(G4int index);
G4TessellatedSolid *GetTessellatedSolid(G4String name, G4bool exact = true);
G4TessellatedSolid *GetTessellatedSolid(std::shared_ptr<Mesh> mesh);
G4AssemblyVolume *GetAssembly();
public:
void SetReverse(G4bool reverse) { this->reverse_ = reverse; };
G4bool GetReverse() { return this->reverse_; };
private:
G4bool reverse_;
};
}
#ifdef USE_CADMESH_TETGEN
#include "tetgen.h"
namespace CADMesh {
class TetrahedralMesh : public CADMeshTemplate<TetrahedralMesh> {
public:
using CADMeshTemplate::CADMeshTemplate;
TetrahedralMesh();
~TetrahedralMesh();
public:
G4VSolid *GetSolid();
G4VSolid *GetSolid(G4int index);
G4VSolid *GetSolid(G4String name, G4bool exact = true);
std::vector<G4VSolid *> GetSolids();
G4AssemblyVolume *GetAssembly();
public:
void SetMaterial(G4Material *material) { this->material_ = material; };
G4Material *GetMaterial() { return this->material_; };
void SetQuality(G4double quality) { this->quality_ = quality; };
G4double GetQuality() { return this->quality_; };
std::shared_ptr<tetgenio> GetTetgenInput() { return in_; };
std::shared_ptr<tetgenio> GetTetgenOutput() { return out_; };
private:
G4ThreeVector GetTetPoint(G4int index_offset);
private:
std::shared_ptr<tetgenio> in_ = nullptr;
std::shared_ptr<tetgenio> out_ = nullptr;
G4double quality_;
G4Material *material_;
};
}
#endif
namespace CADMesh {
namespace File {
inline Type TypeFromExtension(G4String extension) {
std::for_each(extension.begin(), extension.end(),
[](char &e) { e = ::tolower(e); });
for (auto e = Extension.begin(); e != Extension.end(); ++e) {
if (e->second == extension) {
return e->first;
}
}
return Unknown;
}
inline Type TypeFromName(G4String name) {
auto extension = name.substr(name.find_last_of(".") + 1);
return TypeFromExtension(extension);
}
}
}
namespace CADMesh {
inline Mesh::Mesh(Points points, Triangles triangles, G4String name)
: name_(name), points_(points), triangles_(triangles) {}
inline std::shared_ptr<Mesh> Mesh::New(Points points, Triangles triangles,
G4String name) {
return std::make_shared<Mesh>(points, triangles, name);
}
inline std::shared_ptr<Mesh> Mesh::New(Triangles triangles, G4String name) {
Points points;
return New(points, triangles, name);
}
inline std::shared_ptr<Mesh> Mesh::New(std::shared_ptr<Mesh> mesh,
G4String name) {
return New(mesh->GetPoints(), mesh->GetTriangles(), name);
}
inline G4String Mesh::GetName() { return name_; }
inline Points Mesh::GetPoints() { return points_; }
inline Triangles Mesh::GetTriangles() { return triangles_; }
inline G4bool Mesh::IsValidForNavigation() {
std::map<G4ThreeVector, size_t> point_index;
size_t index = 0;
for (auto point : points_) {
point_index[point] = index;
index++;
}
typedef std::pair<size_t, size_t> Edge;
std::map<Edge, G4int> edge_use_count;
for (size_t i = 0; i < triangles_.size(); i++) {
auto triangle = triangles_[i];
size_t a = point_index[triangle->GetVertex(0)];
size_t b = point_index[triangle->GetVertex(1)];
size_t c = point_index[triangle->GetVertex(2)];
if (a < b) {
edge_use_count[Edge(a, b)] += 1;
}
else if (a > b) {
edge_use_count[Edge(b, a)] += 1;
}
if (b < c) {
edge_use_count[Edge(b, c)] += 1;
}
else if (b > c) {
edge_use_count[Edge(c, b)] += 1;
}
if (c < a) {
edge_use_count[Edge(c, a)] += 1;
}
else if (c > a) {
edge_use_count[Edge(a, c)] += 1;
}
}
for (auto count : edge_use_count) {
if (count.second != 2) {
return false;
}
}
return true;
}
}
namespace CADMesh {
namespace File {
inline Reader::Reader(G4String reader_name) : name_(reader_name) {}
inline Reader::~Reader() {}
inline G4String Reader::GetName() { return name_; }
inline std::shared_ptr<Mesh> Reader::GetMesh() {
if (meshes_.size() > 0) {
return meshes_[0];
}
return nullptr;
}
inline std::shared_ptr<Mesh> Reader::GetMesh(size_t index) {
if (index < meshes_.size()) {
return meshes_[index];
}
Exceptions::MeshNotFound("Reader::GetMesh", index);
return nullptr;
}
inline std::shared_ptr<Mesh> Reader::GetMesh(G4String name, G4bool exact) {
for (auto mesh : meshes_) {
if (exact) {
if (mesh->GetName() == name)
return mesh;
}
else {
if (mesh->GetName().find(name) != std::string::npos)
return mesh;
}
}
Exceptions::MeshNotFound("Reader::GetMesh", name);
return nullptr;
}
inline Meshes Reader::GetMeshes() { return meshes_; }
inline size_t Reader::GetNumberOfMeshes() { return meshes_.size(); }
inline size_t Reader::AddMesh(std::shared_ptr<Mesh> mesh) {
meshes_.push_back(mesh);
return meshes_.size();
}
inline void Reader::SetMeshes(Meshes meshes) { meshes_ = meshes; }
}
}
#include <fstream>
#include <sstream>
#include <streambuf>
namespace CADMesh {
namespace File {
inline Lexer::Lexer(std::string filepath, State *initial_state) {
std::ifstream file(filepath);
input_ = std::string((std::istreambuf_iterator<char>(file)),
std::istreambuf_iterator<char>());
if (initial_state) {
Run(initial_state);
}
}
inline std::string Lexer::String() {
return input_.substr(start_, position_ - start_);
}
inline void Lexer::Run(State *initial_state, size_t lines) {
parent_item_ = new Item{ParentToken, position_, line_, "", "",
nullptr, std::vector<Item>()};
state_ = initial_state;
end_line_ = 0;
if (lines > 0)
end_line_ = line_ + lines;
while (state_) {
state_ = (*state_)(this);
}
}
inline Items Lexer::GetItems() { return parent_item_->children; }
inline void Lexer::Backup() {
position_ -= width_;
auto next = input_.substr(position_, 1);
if (next == "\n") {
line_--;
}
}
inline void Lexer::BackupTo(int position) {
auto s = input_.substr(position, position_ - position);
line_ -= std::count(s.begin(), s.end(), '\n');
position_ = position;
}
inline std::string Lexer::Next() {
if (position_ >= input_.length()) {
return "";
}
auto next = input_.substr(position_, 1);
width_ = 1;
position_ += width_;
if (next == "\n")
line_++;
return next;
}
inline std::string Lexer::Peek() {
auto next = Next();
if (next != "")
Backup();
return next;
}
inline void Lexer::Skip() { start_ = position_; }
inline Item *Lexer::ThisIsA(Token token, std::string error) {
if (dry_run_)
return nullptr;
auto item =
Item{token, position_, line_, String(), error, parent_item_, Items()};
Skip();
if (parent_item_) {
PrintItem(item);
parent_item_->children.push_back(item);
return &(parent_item_->children.back());
}
else {
depth_++;
PrintItem(item);
items_.push_back(item);
return &(items_.back());
}
}
inline Item *Lexer::StartOfA(Token token, std::string error) {
if (dry_run_)
return nullptr;
parent_item_ = ThisIsA(token, error);
depth_++;
return parent_item_;
}
inline Item *Lexer::EndOfA(Token token, std::string /*error*/) {
if (dry_run_)
return nullptr;
depth_--;
PrintItem(*parent_item_);
if (parent_item_->token.name != token.name) {
Exceptions::LexerError("Lexer::EndOfA",
"Trying to end a '" + parent_item_->token.name +
"' with a '" + token.name + "' token.");
}
if (parent_item_) {
parent_item_ = parent_item_->parent;
}
return nullptr;
}
inline Item *Lexer::MaybeEndOfA(Token token, std::string error) {
if (parent_item_->token.name == token.name) {
return EndOfA(token, error);
}
else {
return nullptr;
}
}
inline bool Lexer::OneOf(std::string possibles) {
auto peek = Peek();
size_t position = possibles.find(Peek());
if (position != std::string::npos) {
auto next = Next();
return next != "";
}
return false;
}
inline bool Lexer::ManyOf(std::string possibles) {
bool has = false;
while (OneOf(possibles)) {
has = true;
}
return has;
}
inline bool Lexer::Until(std::string match) {
while (!OneOf(match)) {
if (Next() == "")
return false;
}
return true;
}
inline bool Lexer::MatchExactly(std::string match) {
auto start_position = position_;
for (auto m : match) {
if (!OneOf(std::string(1, m))) {
BackupTo(start_position);
return false;
}
}
return true;
}
inline bool Lexer::OneDigit() { return OneOf("0123456789"); }
inline bool Lexer::ManyDigits() { return ManyOf("0123456789"); }
inline bool Lexer::OneLetter() {
return OneOf("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
}
inline bool Lexer::ManyLetters() {
return ManyOf("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
}
inline bool Lexer::ManyCharacters() {
return ManyOf("!\"#$%&\\\'()*+,-./"
"0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[|]^_`"
"abcdefghijklmnopqrstuvwxyz{}~");
}
inline bool Lexer::Integer() {
auto start_position = position_;
OneOf("+-");
if (!ManyDigits()) {
BackupTo(start_position);
return false;
}
return true;
}
inline bool Lexer::Float() {
auto start_position = position_;
OneOf("+-");
bool has_integer = Integer();
if (!OneOf(".")) {
BackupTo(start_position);
return false;
}
bool has_decimal = ManyDigits();
if (!has_integer || !has_decimal) {
BackupTo(start_position);
return false;
}
return true;
}
inline bool Lexer::Number() {
if (!Float()) {
if (!Integer()) {
return false;
}
}
auto start_position = position_;
if (OneOf("eE")) {
if (!Float()) {
if (!Integer()) {
BackupTo(start_position);
}
}
}
return true;
}
inline bool Lexer::SkipWhiteSpace() {
if (!ManyOf(" \t\r")) {
Skip();
return false;
}
Skip();
return true;
}
inline bool Lexer::SkipLineBreak() {
if (!OneOf("\n")) {
return false;
}
Skip();
return true;
}
inline bool Lexer::SkipLineBreaks() {
if (!ManyOf("\n")) {
return false;
}
Skip();
return true;
}
inline bool Lexer::SkipLine() {
if (!Until("\n")) {
return false;
}
Skip();
return true;
}
inline State *Lexer::Error(std::string message) {
std::stringstream error;
error << "Error around line " << line_ << ": " << message << std::endl;
last_error_ = error.str();
if (dry_run_)
return nullptr;
Item item{ErrorToken, position_, line_, "",
error.str(), parent_item_, Items()};
items_.push_back(item);
Exceptions::LexerError("Lexer", error.str());
return nullptr;
}
inline State *Lexer::LastError() {
if (last_error_ == "") {
Exceptions::LexerError("Lexer", "Something went wrong.");
}
else {
Exceptions::LexerError("Lexer", last_error_);
}
return nullptr;
}
inline bool Lexer::TestState(State *state) {
if (dry_run_)
return false;
if (end_line_ > 0 && line_ > end_line_)
return false;
auto start_position = position_;
dry_run_ = true;
bool state_transition = ((*state)(this) != nullptr);
dry_run_ = false;
BackupTo(start_position);
return state_transition;
}
inline bool Lexer::IsDryRun() { return dry_run_; }
inline size_t Lexer::LineNumber() { return line_; }
#ifdef CADMESH_LEXER_VERBOSE
inline void Lexer::PrintMessage(std::string name, std::string message) {
std::cout << "Lexer::" << name << " : " << message << std::endl;
}
#else
inline void Lexer::PrintMessage(std::string, std::string) {}
#endif
#ifdef CADMESH_LEXER_VERBOSE
inline void Lexer::PrintItem(Item item) {
auto depth = std::max(0, depth_) * 2;
std::cout << std::string(depth, ' ') << item.token.name << ": " << item.value
<< std::endl;
}
#else
inline void Lexer::PrintItem(Item) {}
#endif
}
}
namespace CADMesh {
template <typename T>
CADMeshTemplate<T>::CADMeshTemplate() : CADMeshTemplate<T>("") {}
template <typename T>
CADMeshTemplate<T>::CADMeshTemplate(G4String file_name)
: CADMeshTemplate<T>(file_name, File::Unknown) {}
template <typename T>
CADMeshTemplate<T>::CADMeshTemplate(G4String file_name, File::Type file_type)
: CADMeshTemplate<T>(file_name, file_type, File::CADMESH_DEFAULT_READER()) {
}
template <typename T>
CADMeshTemplate<T>::CADMeshTemplate(std::shared_ptr<File::Reader> reader)
: CADMeshTemplate<T>("", reader) {}
template <typename T>
CADMeshTemplate<T>::CADMeshTemplate(G4String file_name,
std::shared_ptr<File::Reader> reader)
: CADMeshTemplate<T>(file_name, File::Unknown, reader) {}
template <typename T>
CADMeshTemplate<T>::CADMeshTemplate(G4String file_name, File::Type file_type,
std::shared_ptr<File::Reader> reader) {
if (!reader->CanRead(file_type)) {
Exceptions::ReaderCantReadError(reader->GetName(), file_type, file_name);
}
file_name_ = file_name;
file_type_ = file_type;
scale_ = 1.0;
offset_ = G4ThreeVector();
verbose_ = 0;
reader_ = reader;
reader_->Read(file_name_);
}
template <typename T>
std::shared_ptr<T> CADMeshTemplate<T>::From(G4String file_name) {
return std::make_shared<T>(file_name);
}
template <typename T>
std::shared_ptr<T>
CADMeshTemplate<T>::From(G4String file_name,
std::shared_ptr<File::Reader> reader) {
return std::make_shared<T>(file_name, reader);
}
template <typename T>
std::shared_ptr<T> CADMeshTemplate<T>::FromPLY(G4String file_name) {
return std::make_shared<T>(file_name, File::PLY);
}
template <typename T>
std::shared_ptr<T>
CADMeshTemplate<T>::FromPLY(G4String file_name,
std::shared_ptr<File::Reader> reader) {
return std::make_shared<T>(file_name, File::PLY, reader);
}
template <typename T>
std::shared_ptr<T> CADMeshTemplate<T>::FromSTL(G4String file_name) {
return std::make_shared<T>(file_name, File::STL);
}
template <typename T>
std::shared_ptr<T>
CADMeshTemplate<T>::FromSTL(G4String file_name,
std::shared_ptr<File::Reader> reader) {
return std::make_shared<T>(file_name, File::STL, reader);
}
template <typename T>
std::shared_ptr<T> CADMeshTemplate<T>::FromOBJ(G4String file_name) {
return std::make_shared<T>(file_name, File::OBJ);
}
template <typename T>
std::shared_ptr<T>
CADMeshTemplate<T>::FromOBJ(G4String file_name,
std::shared_ptr<File::Reader> reader) {
return std::make_shared<T>(file_name, File::OBJ, reader);
}
template <typename T> CADMeshTemplate<T>::~CADMeshTemplate() {}
template <typename T> bool CADMeshTemplate<T>::IsValidForNavigation() {
return reader_->GetMesh()->IsValidForNavigation();
}
template <typename T> G4String CADMeshTemplate<T>::GetFileName() {
return file_name_;
}
template <typename T> File::Type CADMeshTemplate<T>::GetFileType() {
return file_type_;
}
template <typename T> void CADMeshTemplate<T>::SetVerbose(G4int verbose) {
verbose_ = verbose;
}
template <typename T> G4int CADMeshTemplate<T>::GetVerbose() {
return verbose_;
}
template <typename T> void CADMeshTemplate<T>::SetScale(G4double scale) {
scale_ = scale;
}
template <typename T> G4double CADMeshTemplate<T>::GetScale() { return scale_; }
template <typename T>
void CADMeshTemplate<T>::SetOffset(G4double x, G4double y, G4double z) {
SetOffset(G4ThreeVector(x, y, z));
}
template <typename T> void CADMeshTemplate<T>::SetOffset(G4ThreeVector offset) {
offset_ = offset;
}
template <typename T> G4ThreeVector CADMeshTemplate<T>::GetOffset() {
return offset_;
}
}
namespace CADMesh {
namespace Exceptions {
inline void FileNotFound(G4String origin, G4String filepath) {
G4Exception(
("CADMesh in " + origin).c_str(), "FileNotFound", FatalException,
("\nThe file: \n\t" + filepath + "\ncould not be found.").c_str());
}
inline void LexerError(G4String origin, G4String message) {
G4Exception(
("CADMesh in " + origin).c_str(), "LexerError", FatalException,
("\nThe CAD file appears to contain incorrect syntax:\n\t" + message)
.c_str());
}
inline void ParserError(G4String origin, G4String message) {
G4Exception(("CADMesh in " + origin).c_str(), "ParserError", FatalException,
("\nThe CAD file appears to contain invalid data:\n\t" + message)
.c_str());
}
inline void ReaderCantReadError(G4String origin, File::Type file_type,
G4String filepath) {
G4Exception(
("CADMesh in " + origin).c_str(), "ReaderCantReadError", FatalException,
(G4String("\nThe the reader can't read files of type '") +
File::TypeString[file_type] +
".'\n\tSpecified the incorrect file type (?) for file:\n\t\t" + filepath)
.c_str());
}
inline void MeshNotFound(G4String origin, size_t index) {
std::stringstream message;
message << "\nThe mesh with index '" << index << "' could not be found.";
G4Exception(("CADMesh in " + origin).c_str(), "MeshNotFound", FatalException,
message.str().c_str());
}
inline void MeshNotFound(G4String origin, G4String name) {
G4Exception(
("CADMesh in " + origin).c_str(), "MeshNotFound", FatalException,
("\nThe mesh with name '" + name + "' could not be found.").c_str());
}
}
}
#include "Randomize.hh"
namespace CADMesh {
inline G4VSolid *TessellatedMesh::GetSolid() {
return (G4VSolid *)GetTessellatedSolid();
}
inline G4VSolid *TessellatedMesh::GetSolid(G4int index) {
return (G4VSolid *)GetTessellatedSolid(index);
}
inline G4VSolid *TessellatedMesh::GetSolid(G4String name, G4bool exact) {
return (G4VSolid *)GetTessellatedSolid(name, exact);
}
inline std::vector<G4VSolid *> TessellatedMesh::GetSolids() {
std::vector<G4VSolid *> solids;
for (auto mesh : reader_->GetMeshes()) {
solids.push_back(GetTessellatedSolid(mesh));
}
return solids;
}
inline G4AssemblyVolume *TessellatedMesh::GetAssembly() {
if (assembly_) {
return assembly_;
}
for (auto mesh : reader_->GetMeshes()) {
auto solid = GetTessellatedSolid(mesh);
G4Material *material = nullptr;
auto logical =
new G4LogicalVolume(solid, material, mesh->GetName() + "_logical");
G4ThreeVector position = G4ThreeVector();
G4RotationMatrix *rotation = new G4RotationMatrix();
assembly_->AddPlacedVolume(logical, position, rotation);
}
return assembly_;
}
inline G4TessellatedSolid *TessellatedMesh::GetTessellatedSolid() {
return GetTessellatedSolid(0);
}
inline G4TessellatedSolid *TessellatedMesh::GetTessellatedSolid(G4int index) {
return GetTessellatedSolid(reader_->GetMesh(index));
}
inline G4TessellatedSolid *TessellatedMesh::GetTessellatedSolid(G4String name,
G4bool exact) {
return GetTessellatedSolid(reader_->GetMesh(name, exact));
}
inline G4TessellatedSolid *
TessellatedMesh::GetTessellatedSolid(std::shared_ptr<Mesh> mesh) {
auto volume_solid = new G4TessellatedSolid(mesh->GetName());
for (auto triangle : mesh->GetTriangles()) {
auto a = triangle->GetVertex(0) * scale_ + offset_;
auto b = triangle->GetVertex(1) * scale_ + offset_;
auto c = triangle->GetVertex(2) * scale_ + offset_;
auto t = new G4TriangularFacet(a, b, c, ABSOLUTE);
if (reverse_) {
volume_solid->AddFacet((G4VFacet *)t->GetFlippedFacet());
}
else {
volume_solid->AddFacet((G4VFacet *)t);
}
}
volume_solid->SetSolidClosed(true);
if (volume_solid->GetNumberOfFacets() == 0) {
G4Exception("TessellatedMesh::GetTessellatedSolid",
"The loaded mesh has 0 faces.", FatalException,
"The file may be empty.");
return nullptr;
}
return volume_solid;
}
}
#ifdef USE_CADMESH_TETGEN
namespace CADMesh {
inline TetrahedralMesh::TetrahedralMesh() {}
inline TetrahedralMesh::~TetrahedralMesh() {}
inline G4VSolid *TetrahedralMesh::GetSolid() { return GetSolid(0); }
inline G4VSolid *TetrahedralMesh::GetSolid(G4int /*index*/) { return nullptr; }
inline G4VSolid *TetrahedralMesh::GetSolid(G4String /*name*/,
G4bool /*exact*/) {
return nullptr;
}
inline std::vector<G4VSolid *> TetrahedralMesh::GetSolids() {
return std::vector<G4VSolid *>();
}
inline G4AssemblyVolume *TetrahedralMesh::GetAssembly() {
if (assembly_) {
return assembly_;
}
assembly_ = new G4AssemblyVolume();
in_ = std::make_shared<tetgenio>();
out_ = std::make_shared<tetgenio>();
char *fn = (char *)file_name_.c_str();
G4bool do_tet = true;
if (file_type_ == File::STL) {
in_->load_stl(fn);
}
else if (file_type_ == File::PLY) {
in_->load_ply(fn);
}
else if (file_type_ == File::TET) {
out_->load_tetmesh(fn, 0);
do_tet = false;
}
else if (file_type_ == File::OFF) {
out_->load_off(fn);
do_tet = false;
}
if (do_tet) {
tetgenbehavior *behavior = new tetgenbehavior();
behavior->nobisect = 1;
behavior->plc = 1;
behavior->quality = quality_;
tetrahedralize(behavior, in_.get(), out_.get());
}
G4RotationMatrix *element_rotation = new G4RotationMatrix();
G4ThreeVector element_position = G4ThreeVector();
G4Transform3D assembly_transform = G4Translate3D();
for (int i = 0; i < out_->numberoftetrahedra; i++) {
int index_offset = i * 4;
G4ThreeVector p1 = GetTetPoint(index_offset);
G4ThreeVector p2 = GetTetPoint(index_offset + 1);
G4ThreeVector p3 = GetTetPoint(index_offset + 2);
G4ThreeVector p4 = GetTetPoint(index_offset + 3);
G4String tet_name =
file_name_ + G4String("_tet_") + G4UIcommand::ConvertToString(i);
auto tet_solid =
new G4Tet(tet_name + G4String("_solid"), p1, p2, p3, p4, 0);
auto tet_logical = new G4LogicalVolume(
tet_solid, material_, tet_name + G4String("_logical"), 0, 0, 0);
assembly_->AddPlacedVolume(tet_logical, element_position, element_rotation);
}
return assembly_;
}
inline G4ThreeVector TetrahedralMesh::GetTetPoint(G4int index_offset) {
return G4ThreeVector(
out_->pointlist[out_->tetrahedronlist[index_offset] * 3] * scale_ -
offset_.x(),
out_->pointlist[out_->tetrahedronlist[index_offset] * 3 + 1] * scale_ -
offset_.y(),
out_->pointlist[out_->tetrahedronlist[index_offset] * 3 + 2] * scale_ -
offset_.z());
}
}
#endif
#define CADMeshLexerToken(name) \
static Token name##Token { #name }
#define CADMeshLexerStateDefinition(name) \
struct name##State : public State { \
State *operator()(Lexer *lexer) const; \
}
#define CADMeshLexerState(name) name##State::operator()(Lexer *lexer) const
#define ThisIsA(name) lexer->ThisIsA(name##Token)
#define StartOfA(name) lexer->StartOfA(name##Token)
#define EndOfA(name) lexer->EndOfA(name##Token)
#define MaybeEndOfA(name) lexer->MaybeEndOfA(name##Token)
#define Skip() lexer->Skip()
#define Next() lexer->Peek()
#define PrintNext() std::cout << lexer->Peek() << std::endl;
#define OneOf(possibles) lexer->OneOf(possibles)
#define NotOneOf(possibles) !OneOf(possibles)
#define ManyOf(possibles) lexer->ManyOf(possibles)
#define NotManyOf(possibles) !ManyOf(possibles)
#define Until(match) lexer->Until(match)
#define RestOfLine() \
if (Until("\n\r")) \
lexer->Backup()
#define MatchExactly(match) lexer->MatchExactly(match)
#define DoesNotMatchExactly(match) !MatchExactly(match)
#define OneDigit() lexer->OneDigit()
#define NotOneDigit() !OneDigit()
#define ManyDigits() lexer->ManyDigits()
#define NotManyDigits() !ManyDigits()
#define OneLetter() lexer->OneLetter()
#define NotOneLetter() !OneLetter()
#define ManyLetters() lexer->ManyLetters()
#define NotManyLetters() !ManyLetters()
#define ManyCharacters() lexer->ManyCharacters()
#define NotManyCharacters() !ManyCharacters()
#define Integer() lexer->Integer()
#define NotAnInteger() !Integer()
#define Float() lexer->Float()
#define NotAFloat() !Float()
#define Number() lexer->Number()
#define NotANumber() !Number()
#define SkipWhiteSpace() lexer->SkipWhiteSpace()
#define DidNotSkipWhiteSpace() !SkipWhiteSpace()
#define SkipLineBreak() lexer->SkipLineBreak()
#define DidNotSkipLineBreak() !SkipLineBreak()
#define SkipLineBreaks() lexer->SkipLineBreaks()
#define DidNotSkipLineBreaks() !SkipLineBreaks()
#define SkipLine() lexer->SkipLine()
#define DidNotSkipLine() !SkipLine()
#define AtEndOfLine() Next() == "\n" || Next() == "\r"
#define Error(message) \
{ \
lexer->Error(message); \
return nullptr; \
}
#define NextState(next) return new next##State()
#define TestState(next) lexer->TestState(new next##State())
#define TryState(next) \
if (TestState(next)) \
NextState(next)
#define FinalState() return new __FinalState();
#define RunLexer(filepath, start) Lexer(filepath, new start##State).GetItems()
namespace CADMesh {
namespace File {
class STLReader : public Reader {
public:
STLReader() : Reader("STLReader"){};
G4bool Read(G4String filepath);
G4bool CanRead(Type file_type);
protected:
CADMeshLexerStateDefinition(StartSolid);
CADMeshLexerStateDefinition(EndSolid);
CADMeshLexerStateDefinition(StartFacet);
CADMeshLexerStateDefinition(EndFacet);
CADMeshLexerStateDefinition(StartVertices);
CADMeshLexerStateDefinition(EndVertices);
CADMeshLexerStateDefinition(Vertex);
CADMeshLexerStateDefinition(ThreeVector);
std::shared_ptr<Mesh> ParseMesh(Items items);
G4TriangularFacet *ParseFacet(Items items);
G4TriangularFacet *ParseVertices(Items items);
G4ThreeVector ParseThreeVector(Items items);
};
}
}
namespace CADMesh {
namespace File {
class OBJReader : public Reader {
public:
OBJReader() : Reader("OBJReader"){};
G4bool Read(G4String filepath);
G4bool CanRead(Type file_type);
protected:
CADMeshLexerStateDefinition(StartSolid);
CADMeshLexerStateDefinition(EndSolid);
CADMeshLexerStateDefinition(Ignore);
CADMeshLexerStateDefinition(Vertex);
CADMeshLexerStateDefinition(Facet);
CADMeshLexerStateDefinition(Object);
std::shared_ptr<Mesh> ParseMesh(Items items);
G4ThreeVector ParseVertex(Items items);
G4TriangularFacet *ParseFacet(Items items, G4bool quad);
private:
Points vertices_;
};
}
}
namespace CADMesh {
namespace File {
CADMeshLexerToken(Header);
CADMeshLexerToken(Element);
CADMeshLexerToken(Property);
class PLYReader : public Reader {
public:
PLYReader() : Reader("PLYReader"){};
G4bool Read(G4String filepath);
G4bool CanRead(Type file_type);
protected:
CADMeshLexerStateDefinition(StartHeader);
CADMeshLexerStateDefinition(EndHeader);
CADMeshLexerStateDefinition(Element);
CADMeshLexerStateDefinition(Property);
CADMeshLexerStateDefinition(Ignore);
CADMeshLexerStateDefinition(Vertex);
CADMeshLexerStateDefinition(Facet);
void ParseHeader(Items items);
std::shared_ptr<Mesh> ParseMesh(Items vertex_items, Items face_items);
G4ThreeVector ParseVertex(Items items);
G4TriangularFacet *ParseFacet(Items items, Points vertices);
size_t vertex_count_ = 0;
size_t facet_count_ = 0;
size_t x_index_ = 0;
size_t y_index_ = 0;
size_t z_index_ = 0;
size_t facet_index_ = 0;
};
}
}
namespace CADMesh {
namespace File {
inline State *STLReader::CADMeshLexerState(StartSolid) {
if (DoesNotMatchExactly("solid"))
Error("STL files start with 'solid'. Make sure you are using an ASCII STL "
"file.");
SkipWhiteSpace();
RestOfLine();
StartOfA(Solid);
SkipLineBreak();
NextState(StartFacet);
}
inline State *STLReader::CADMeshLexerState(EndSolid) {
SkipWhiteSpace();
SkipLineBreaks();
SkipWhiteSpace();
if (DoesNotMatchExactly("endsolid"))
Error("STL files end with 'endsolid'.");
Skip();
EndOfA(Solid);
FinalState();
}
inline State *STLReader::CADMeshLexerState(StartFacet) {
SkipWhiteSpace();
SkipLineBreaks();
SkipWhiteSpace();
if (DoesNotMatchExactly("facet normal"))
Error("Facets are indicated by the tag 'facet normal'.");
SkipWhiteSpace();
StartOfA(Facet);
SkipLine();
NextState(StartVertices);
}
inline State *STLReader::CADMeshLexerState(EndFacet) {
SkipWhiteSpace();
SkipLineBreaks();
SkipWhiteSpace();
if (DoesNotMatchExactly("endfacet"))
Error("The end of a facets is indicated by the tag 'endfacet'.");
SkipWhiteSpace();
SkipLineBreak();
EndOfA(Facet);
TryState(StartFacet);
NextState(EndSolid);
}
inline State *STLReader::CADMeshLexerState(StartVertices) {
SkipWhiteSpace();
SkipLineBreaks();
SkipWhiteSpace();
if (DoesNotMatchExactly("outer loop"))
Error("The start of the vertices is indicated by the tag 'outer loop'.");
SkipWhiteSpace();
SkipLineBreak();
StartOfA(Vertices);
NextState(Vertex);
}
inline State *STLReader::CADMeshLexerState(EndVertices) {
SkipWhiteSpace();
SkipLineBreaks();
SkipWhiteSpace();
if (DoesNotMatchExactly("endloop"))
Error("The end of the vertices is indicated by the tag 'endloop'.");
SkipWhiteSpace();
SkipLineBreak();
EndOfA(Vertices);
NextState(EndFacet);
}
inline State *STLReader::CADMeshLexerState(Vertex) {
SkipWhiteSpace();
SkipLineBreaks();
SkipWhiteSpace();
if (DoesNotMatchExactly("vertex"))
Error("A vertex is indicated by the tag 'vertex'.");
SkipWhiteSpace();
NextState(ThreeVector);
}
inline State *STLReader::CADMeshLexerState(ThreeVector) {
SkipWhiteSpace();
StartOfA(ThreeVector);
if (NotANumber())
Error("First number in three vector not found.");
ThisIsA(Number);
SkipWhiteSpace();
if (NotANumber())
Error("Second number in three vector not found.");
ThisIsA(Number);
SkipWhiteSpace();
if (NotANumber())
Error("Third number in three vector not found.");
ThisIsA(Number);
EndOfA(ThreeVector);
SkipWhiteSpace();
if (DidNotSkipLineBreak())
Error("Expecting a new line at the end of a three vector.");
TryState(StartVertices);
TryState(Vertex);
NextState(EndVertices);
}
inline G4bool STLReader::Read(G4String filepath) {
auto items = RunLexer(filepath, StartSolid);
if (items.size() == 0) {
Exceptions::ParserError("STLReader::Read",
"The STL file appears to be empty.");
}
for (auto item : items) {
if (item.children.size() == 0) {
std::stringstream error;
error << "The mesh appears to be empty."
<< "Error around line " << item.line << ".";
Exceptions::ParserError("STLReader::Read", error.str());
}
auto mesh = ParseMesh(item.children);
auto name = G4String(item.value);
AddMesh(Mesh::New(mesh, name));
}
return true;
}
inline G4bool STLReader::CanRead(Type file_type) { return (file_type == STL); }
inline std::shared_ptr<Mesh> STLReader::ParseMesh(Items items) {
Triangles triangles;
for (auto item : items) {
if (item.children.size() == 0) {
std::stringstream error;
error << "The facet appears to be empty."
<< "Error around line " << item.line << ".";
Exceptions::ParserError("STLReader::Mesh", error.str());
}
triangles.push_back(ParseFacet(item.children));
}
return Mesh::New(triangles);
}
inline G4TriangularFacet *STLReader::ParseFacet(Items items) {
Triangles triangles;
for (auto item : items) {
if (item.children.size() == 0) {
std::stringstream error;
error << "The vertex appears to be empty."
<< "Error around line " << item.line << ".";
Exceptions::ParserError("STLReader::ParseFacet", error.str());
}
triangles.push_back(ParseVertices(item.children));
}
if (triangles.size() != 1) {
std::stringstream error;
error << "STL files expect exactly 1 triangle per facet.";
if (items.size() != 0) {
error << "Error around line " << items[0].line << ".";
}
Exceptions::ParserError("STLReader::ParseFacet", error.str());
}
return triangles[0];
}
inline G4TriangularFacet *STLReader::ParseVertices(Items items) {
std::vector<G4ThreeVector> vertices;
for (auto item : items) {
if (item.children.size() == 0) {
std::stringstream error;
error << "The vertex appears to be empty."
<< "Error around line " << item.line << ".";
Exceptions::ParserError("STLReader::ParseVertices", error.str());
}
vertices.push_back(ParseThreeVector(item.children));
}
if (vertices.size() != 3) {
std::stringstream error;
error << "STL files expect exactly 3 vertices for a triangular facet. ";
if (items.size() != 0) {
error << "Error around line " << items[0].line << ".";
}
Exceptions::ParserError("STLReader::ParseVertices", error.str());
}
return new G4TriangularFacet(vertices[0], vertices[1], vertices[2], ABSOLUTE);
}
inline G4ThreeVector STLReader::ParseThreeVector(Items items) {
std::vector<double> numbers;
for (auto item : items) {
numbers.push_back((double)atof(item.value.c_str()));
}
if (numbers.size() != 3) {
std::stringstream error;
error << "Three vectors in STL files require exactly 3 numbers";
if (items.size() != 0) {
error << "Error around line " << items[0].line << ".";
}
Exceptions::ParserError("STLReader::ParseThreeVector", error.str());
}
return G4ThreeVector(numbers[0], numbers[1], numbers[2]);
}
}
}
namespace CADMesh {
namespace File {
inline State *OBJReader::CADMeshLexerState(StartSolid) {
StartOfA(Solid);
TryState(Object);
TryState(Vertex);
TryState(Ignore);
Error("Invalid element tag.");
}
inline State *OBJReader::CADMeshLexerState(EndSolid) {
if (Next() != "")
lexer->LastError();
EndOfA(Solid);
FinalState();
}
inline State *OBJReader::CADMeshLexerState(Ignore) {
if (DidNotSkipLine())
NextState(EndSolid);
TryState(Object);
TryState(Vertex);
TryState(Facet);
TryState(Ignore);
NextState(EndSolid);
}
inline State *OBJReader::CADMeshLexerState(Vertex) {
SkipLineBreaks();
if (DoesNotMatchExactly("v "))
Error("A vertex is indicated by the tag 'v'.");
SkipWhiteSpace();
StartOfA(Vertex);
if (NotANumber())
Error("First number in three vector not found.");
ThisIsA(Number);
SkipWhiteSpace();
if (NotANumber())
Error("Second number in three vector not found.");
ThisIsA(Number);
SkipWhiteSpace();
if (NotANumber())
Error("Third number in three vector not found.");
ThisIsA(Number);
EndOfA(Vertex);
SkipLine();
TryState(Vertex);
TryState(Object);
TryState(Facet);
TryState(Ignore);
NextState(EndSolid);
}
inline State *OBJReader::CADMeshLexerState(Facet) {
SkipLineBreaks();
if (DoesNotMatchExactly("f "))
Error("A facet is indicated by the tag 'f'.");
SkipWhiteSpace();
StartOfA(Facet);
if (NotANumber())
Error("First number in three vector not found.");
ThisIsA(Number);
OneOf("/");
Number();
OneOf("/");
Number();
SkipWhiteSpace();
if (NotANumber())
Error("Second number in three vector not found.");
ThisIsA(Number);
OneOf("/");
Number();
OneOf("/");
Number();
SkipWhiteSpace();
if (NotANumber())
Error("Third number in three vector not found.");
ThisIsA(Number);
OneOf("/");
Number();
OneOf("/");
Number();
SkipWhiteSpace();
if (Number())
ThisIsA(Number);
EndOfA(Facet);
SkipLine();
TryState(Facet);
TryState(Vertex);
TryState(Object);
TryState(Ignore);
NextState(EndSolid);
}
inline State *OBJReader::CADMeshLexerState(Object) {
SkipLineBreaks();
if (DoesNotMatchExactly("o "))
Error("An object is indicated by the tag 'o'.");
EndOfA(Solid);
SkipWhiteSpace();
StartOfA(Solid);
ManyCharacters();
ThisIsA(Word);
SkipWhiteSpace();
TryState(Vertex);
TryState(Facet);
TryState(Object);
TryState(Ignore);
NextState(EndSolid);
}
inline G4bool OBJReader::Read(G4String filepath) {
auto items = RunLexer(filepath, StartSolid);
if (items.size() == 0) {
Exceptions::ParserError("OBJReader::Read",
"The OBJ file appears to be empty.");
}
for (auto item : items) {
if (item.children.size() == 0) {
continue;
}
auto mesh = ParseMesh(item.children);
if (mesh->GetTriangles().size() == 0) {
continue;
}
G4String name;
if (item.children[0].token == WordToken) {
name = item.children[0].value;
}
AddMesh(Mesh::New(mesh, name));
}
return true;
}
inline G4bool OBJReader::CanRead(Type file_type) { return (file_type == OBJ); }
inline std::shared_ptr<Mesh> OBJReader::ParseMesh(Items items) {
Triangles facets;
for (auto item : items) {
if (item.token != VertexToken) {
continue;
}
if (item.children.size() == 0) {
std::stringstream error;
error << "The vertex appears to be empty."
<< "Error around line " << item.line << ".";
Exceptions::ParserError("OBJReader::Mesh", error.str());
}
vertices_.push_back(ParseVertex(item.children));
}
for (auto item : items) {
if (item.token != FacetToken) {
continue;
}
if (item.children.size() == 0) {
std::stringstream error;
error << "The facet appears to be empty."
<< "Error around line " << item.line << ".";
Exceptions::ParserError("OBJReader::Mesh", error.str());
}
facets.push_back(ParseFacet(item.children, false));
if (item.children.size() == 4) {
facets.push_back(ParseFacet(item.children, true));
}
}
return Mesh::New(facets);
}
inline G4ThreeVector OBJReader::ParseVertex(Items items) {
std::vector<double> numbers;
for (auto item : items) {
numbers.push_back((double)atof(item.value.c_str()));
}
if (numbers.size() != 3) {
std::stringstream error;
error << "Three vectors in OBJ files require exactly 3 numbers";
if (items.size() != 0) {
error << "Error around line " << items[0].line << ".";
}
Exceptions::ParserError("OBJReader::ParseThreeVector", error.str());
}
return G4ThreeVector(numbers[0], numbers[1], numbers[2]);
}
inline G4TriangularFacet *OBJReader::ParseFacet(Items items, G4bool quad) {
std::vector<int> indices;
for (auto item : items) {
indices.push_back((int)atoi(item.value.c_str()));
}
if (indices.size() < 3) {
std::stringstream error;
error << "Facets in OBJ files require at least 3 indicies";
if (items.size() != 0) {
error << "Error around line " << items[0].line << ".";
}
Exceptions::ParserError("OBJReader::ParseFacet", error.str());
}
if (quad && indices.size() != 4) {
std::stringstream error;
error << "Trying to triangle-ify a facet that isn't a quad";
if (items.size() != 0) {
error << "Error around line " << items[0].line << ".";
}
Exceptions::ParserError("OBJReader::ParseFacet", error.str());
}
if (quad) {
return new G4TriangularFacet(vertices_[indices[0] - 1],
vertices_[indices[2] - 1],
vertices_[indices[3] - 1], ABSOLUTE);
}
else {
return new G4TriangularFacet(vertices_[indices[0] - 1],
vertices_[indices[1] - 1],
vertices_[indices[2] - 1], ABSOLUTE);
}
}
}
}
namespace CADMesh {
namespace File {
inline State *PLYReader::CADMeshLexerState(StartHeader) {
if (DoesNotMatchExactly("ply"))
Error("PLY files start with 'ply'.");
StartOfA(Header);
SkipLine();
TryState(Element);
TryState(Ignore);
Error("Invalid header tag.");
}
inline State *PLYReader::CADMeshLexerState(EndHeader) {
if (DoesNotMatchExactly("end_header"))
Error("PLY file headers end with 'end_header'.");
MaybeEndOfA(Element);
EndOfA(Header);
FinalState();
}
inline State *PLYReader::CADMeshLexerState(Element) {
if (DoesNotMatchExactly("element "))
Error("An element is indicated by the tag 'element'.");
MaybeEndOfA(Element);
SkipWhiteSpace();
StartOfA(Element);
if (NotManyCharacters())
Error("Element type not found.");
ThisIsA(Word);
SkipWhiteSpace();
if (NotANumber())
Error("Element count not found.");
ThisIsA(Number);
SkipLine();
TryState(Property);
TryState(Ignore);
NextState(EndHeader);
}
inline State *PLYReader::CADMeshLexerState(Property) {
if (DoesNotMatchExactly("property "))
Error("An property is indicated by the tag 'property'.");
SkipWhiteSpace();
StartOfA(Property);
if (NotManyCharacters())
Error("Element type not found.");
ThisIsA(Word);
SkipWhiteSpace();
RestOfLine();
ThisIsA(Word);
EndOfA(Property);
SkipLineBreak();
TryState(Property);
TryState(Element);
TryState(EndHeader);
TryState(Ignore);
NextState(EndHeader);
}
inline State *PLYReader::CADMeshLexerState(Ignore) {
if (DidNotSkipLine())
NextState(EndHeader);
TryState(Element);
TryState(Property);
TryState(EndHeader);
NextState(Ignore);
}
inline State *PLYReader::CADMeshLexerState(Vertex) {
SkipLineBreaks();
SkipWhiteSpace();
SkipLineBreaks();
StartOfA(Vertex);
size_t i = 0;
while (i < 32) {
if (AtEndOfLine())
break;
SkipWhiteSpace();
if (NotANumber())
Error("Expecting only numbers in the vertex specification.");
ThisIsA(Number);
SkipWhiteSpace();
i++;
}
EndOfA(Vertex);
SkipLine();
TryState(Vertex);
FinalState();
}
inline State *PLYReader::CADMeshLexerState(Facet) {
SkipLineBreaks();
SkipWhiteSpace();
SkipLineBreaks();
StartOfA(Facet);
size_t i = 0;
while (i < 32) {
if (AtEndOfLine())
break;
SkipWhiteSpace();
if (NotANumber())
Error("Expecting only numbers in the facet specification.");
ThisIsA(Number);
SkipWhiteSpace();
i++;
}
EndOfA(Facet);
SkipLine();
TryState(Facet);
FinalState();
}
inline G4bool PLYReader::Read(G4String filepath) {
auto lexer = Lexer(filepath, new StartHeaderState);
auto items = lexer.GetItems();
if (items.size() == 0) {
std::stringstream error;
error << "The header appears to be empty.";
Exceptions::ParserError("PLYReader::Read", error.str());
}
ParseHeader(items);
lexer.Run(new VertexState, vertex_count_);
auto vertex_items = lexer.GetItems();
if (vertex_items.size() == 0) {
Exceptions::ParserError("PLYReader::Read",
"The PLY file appears to have no vertices.");
}
if (vertex_items.size() != vertex_count_) {
Exceptions::ParserError("PLYReader::Read",
"The PLY file appears to be missing vertices.");
}
lexer.Run(new FacetState, facet_count_);
auto face_items = lexer.GetItems();
if (face_items.size() == 0) {
Exceptions::ParserError("PLYReader::Read",
"The PLY file appears to have no facets.");
}
if (face_items.size() != facet_count_) {
Exceptions::ParserError("PLYReader::Read",
"The PLY file appears to be missing facets");
}
auto mesh = ParseMesh(vertex_items, face_items);
AddMesh(Mesh::New(mesh));
return true;
}
inline G4bool PLYReader::CanRead(Type file_type) { return (file_type == PLY); }
inline void PLYReader::ParseHeader(Items items) {
if (items.size() != 1) {
std::stringstream error;
error << "The header appears to be invalid or missing."
<< "Error around line 1.";
Exceptions::ParserError("PLYReader::ParseHeader", error.str());
}
for (auto item : items[0].children) {
if (item.token == ElementToken) {
if (item.children.size() < 2) {
std::stringstream error;
error << "Invalid element information in header. Expecting 'vertex' or "
"'face' and a number."
<< "Error around line " << item.line << ".";
Exceptions::ParserError("PLYReader::ParseHeader", error.str());
}
if (item.children[0].token == WordToken &&
item.children[1].token == NumberToken) {
if (item.children[0].value == "vertex") {
vertex_count_ = atoi(item.children[1].value.c_str());
for (size_t i = 2; i < item.children.size(); i++) {
auto property = item.children[i];
if (property.children.size() > 1) {
if (property.children[1].token == WordToken) {
if (property.children[1].value == "x") {
x_index_ = i - 2;
}
if (property.children[1].value == "y") {
y_index_ = i - 2;
}
if (property.children[1].value == "z") {
z_index_ = i - 2;
}
}
}
}
}
else if (item.children[0].value == "face") {
facet_count_ = atoi(item.children[1].value.c_str());
for (size_t i = 2; i < item.children.size(); i++) {
auto property = item.children[i];
if (property.children.size() > 1) {
if (property.children[1].token == WordToken) {
if (property.children[1].value == "uchar int vertex_indices") {
facet_index_ = i - 2;
}
}
}
}
}
}
}
}
if (vertex_count_ == 0) {
std::stringstream error;
error << "The number of vertices was not found in the header.";
Exceptions::ParserError("PLYReader::ParseHeader", error.str());
}
if (facet_count_ == 0) {
std::stringstream error;
error << "The number of faces was not found in the header.";
Exceptions::ParserError("PLYReader::ParseHeader", error.str());
}
if ((x_index_ == y_index_) || (y_index_ == z_index_) ||
(x_index_ == z_index_)) {
std::stringstream error;
error << "The vertex x, y, z indices were not found in the header.";
Exceptions::ParserError("PLYReader::ParseHeader", error.str());
}
}
inline std::shared_ptr<Mesh> PLYReader::ParseMesh(Items vertex_items,
Items face_items) {
Points vertices;
Triangles facets;
for (auto item : vertex_items) {
if (item.children.size() == 0) {
std::stringstream error;
error << "The vertex appears to be empty."
<< "Error around line " << item.line << ".";
Exceptions::ParserError("PLYReader::ParseMesh", error.str());
}
if (item.token == VertexToken) {
vertices.push_back(ParseVertex(item.children));
}
}
for (auto item : face_items) {
if (item.children.size() == 0) {
std::stringstream error;
error << "The facet appears to be empty."
<< "Error around line " << item.line << ".";
Exceptions::ParserError("PLYReader::Mesh", error.str());
}
if (item.token == FacetToken) {
facets.push_back(ParseFacet(item.children, vertices));
}
}
return Mesh::New(facets);
}
inline G4ThreeVector PLYReader::ParseVertex(Items items) {
std::vector<double> numbers;
for (auto item : items) {
numbers.push_back((double)atof(item.value.c_str()));
}
if (numbers.size() < 3) {
std::stringstream error;
error << "Vertices in PLY files require atleast 3 numbers. ";
if (items.size() != 0) {
error << "Error around line " << items[0].line << ".";
}
Exceptions::ParserError("PLYReader::ParseVertex", error.str());
}
return G4ThreeVector(numbers[x_index_], numbers[y_index_], numbers[z_index_]);
}
inline G4TriangularFacet *PLYReader::ParseFacet(Items items, Points vertices) {
std::vector<int> indices;
for (auto item : items) {
indices.push_back((int)atoi(item.value.c_str()));
}
if (indices.size() < 4) {
std::stringstream error;
error << "Facets in PLY files require 3 indicies";
if (items.size() != 0) {
error << "Error around line " << items[0].line << ".";
}
Exceptions::ParserError("PLYReader::ParseFacet", error.str());
}
return new G4TriangularFacet(vertices[indices[1 + facet_index_]],
vertices[indices[2 + facet_index_]],
vertices[indices[3 + facet_index_]], ABSOLUTE);
}
}
}
#ifdef USE_CADMESH_ASSIMP_READER
namespace CADMesh {
namespace File {
inline ASSIMPReader::ASSIMPReader() : Reader("ASSIMPReader") {
importer_ = new Assimp::Importer();
}
inline ASSIMPReader::~ASSIMPReader() { delete importer_; }
inline G4bool ASSIMPReader::Read(G4String filepath) {
auto scene = importer_->ReadFile(filepath.c_str(),
aiProcess_Triangulate |
aiProcess_JoinIdenticalVertices |
aiProcess_CalcTangentSpace);
if (!scene) {
Exceptions::FileNotFound("ASSIMP::Read", filepath);
return false;
}
for (unsigned int index = 0; index < scene->mNumMeshes; index++) {
aiMesh *mesh = scene->mMeshes[index];
auto name = mesh->mName.C_Str();
Triangles triangles;
for (unsigned int i = 0; i < mesh->mNumFaces; i++) {
const aiFace &face = mesh->mFaces[i];
G4ThreeVector a(mesh->mVertices[face.mIndices[0]].x,
mesh->mVertices[face.mIndices[0]].y,
mesh->mVertices[face.mIndices[0]].z);
G4ThreeVector b(mesh->mVertices[face.mIndices[1]].x,
mesh->mVertices[face.mIndices[1]].y,
mesh->mVertices[face.mIndices[1]].z);
G4ThreeVector c(mesh->mVertices[face.mIndices[2]].x,
mesh->mVertices[face.mIndices[2]].y,
mesh->mVertices[face.mIndices[2]].z);
triangles.push_back(new G4TriangularFacet(a, b, c, ABSOLUTE));
}
AddMesh(Mesh::New(triangles, name));
}
return true;
}
inline G4bool ASSIMPReader::CanRead(Type /*file_type*/) { return true; }
std::shared_ptr<ASSIMPReader> ASSIMP() {
return std::make_shared<ASSIMPReader>();
}
}
}
#endif
namespace CADMesh {
namespace File {
inline G4bool BuiltInReader::Read(G4String filepath) {
File::Reader *reader = nullptr;
auto type = TypeFromName(filepath);
if (type == STL) {
reader = new File::STLReader();
}
else if (type == OBJ) {
reader = new File::OBJReader();
}
else if (type == PLY) {
reader = new File::PLYReader();
}
else {
Exceptions::ReaderCantReadError("BuildInReader::Read", type, filepath);
}
if (!reader->Read(filepath)) {
return false;
}
SetMeshes(reader->GetMeshes());
return true;
}
inline G4bool BuiltInReader::CanRead(Type type) {
return type == STL || type == OBJ || type == PLY;
}
inline std::shared_ptr<BuiltInReader> BuiltIn() {
return std::make_shared<BuiltInReader>();
}
}
}
......@@ -38,13 +38,9 @@
#include "G4LogicalVolume.hh"
#include "G4VUserDetectorConstruction.hh"
#include "G4SubtractionSolid.hh"
#include "G4GDMLParser.hh"
// #include "G4GDMLParser.hh"
#include "G4RunManager.hh"
#ifdef CADMESH
#include "CADMesh.hh"
#endif
#include "Materials.hh"
#include "DetectorMessenger.hh"
......@@ -57,6 +53,7 @@ class DetectorConstruction : public G4VUserDetectorConstruction
public:
virtual G4VPhysicalVolume* Construct();
void ConstructSDandField();
void BuildWorld ();
void BuildTrapezoidLG ();
......@@ -103,10 +100,6 @@ class DetectorConstruction : public G4VUserDetectorConstruction
G4LogicalVolume* m_logicHalfWorld;
G4VPhysicalVolume* m_physHalfWorld;
#ifdef CADMESH
CADMesh* m_mesh;
#endif
G4Trd* m_inner;
G4Trd* m_outter;
G4SubtractionSolid* m_LightGuide;
......@@ -123,7 +116,7 @@ class DetectorConstruction : public G4VUserDetectorConstruction
G4Material* m_filler;
G4MaterialPropertiesTable* m_GasMPT;
G4GDMLParser m_Parser;
// G4GDMLParser m_Parser;
G4RunManager* m_runMan;
DetectorMessenger* m_DetectorMessenger;
};
......
......@@ -29,8 +29,6 @@
#include "globals.hh"
#include "G4UserEventAction.hh"
#include <vector>
class EventAction : public G4UserEventAction{
public:
......@@ -40,14 +38,6 @@ class EventAction : public G4UserEventAction{
virtual void BeginOfEventAction( const G4Event* event );
virtual void EndOfEventAction( const G4Event* event );
inline std::vector< std::vector<double>* > GetVectors( ){return fPtrVec;}
private:
G4int hitsCollID;
G4int fEventNo;
std::vector<double> x,z,xHit,zHit,time,theta,energy;
std::vector< std::vector<double>* > fPtrVec;
};
#endif
......@@ -48,6 +48,9 @@ public:
private:
int HCID;
HitsCollection* hitCollection;
std::vector< std::vector<double>* > fPtrVec;
bool VISUALIZE;
};
#endif
......@@ -28,13 +28,17 @@
#ifndef PrimaryGeneratorAction_h
#define PrimaryGeneratorAction_h 1
#include "TFile.h"
#include "TTree.h"
#include "G4VUserPrimaryGeneratorAction.hh"
#include "PrimaryGeneratorMessenger.hh"
#include "ASCIIPrimaryGenerator.hh"
#include "globals.hh"
#include "G4GeneralParticleSource.hh"
#include <vector>
class G4GeneralParticleSource;
class G4Event;
......@@ -47,14 +51,21 @@ class PrimaryGeneratorAction : public G4VUserPrimaryGeneratorAction
public:
virtual void GeneratePrimaries(G4Event*);
virtual void GeneratePrimariesFromRootFile(G4Event*);
virtual void SetInputFile(G4String _name);
inline G4int GetnEvents(){return fASCIIParticleGun->GetnEvents();}
inline G4int GetnEvents(){return fnEvents;}
private:
G4GeneralParticleSource* fParticleGun;
ASCIIPrimaryGenerator* fASCIIParticleGun;
PrimaryGeneratorMessenger* fMessenger;
G4bool fUseInput;
G4int fnEvents;
G4bool fUseASCIIInput;
G4bool fUseRootInput;
TFile* fInputFile;
TTree* fInputTree;
std::vector<G4double> *x, *z, *px, *py, *pz, *Energy, *time;
G4int evNo;
};
......
......@@ -37,6 +37,8 @@
#include "globals.hh"
#include "G4UserRunAction.hh"
#include <vector>
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
class G4Timer;
......@@ -52,9 +54,14 @@ class RunAction : public G4UserRunAction
virtual void BeginOfRunAction(const G4Run* aRun);
virtual void EndOfRunAction(const G4Run* aRun);
std::vector< std::vector<double>* > GetVectors(){ return fPtrVec; }
inline void ClearVectors(){ for(auto vec : fPtrVec) vec->clear(); }
private:
G4Timer* fTimer;
G4String m_fileName;
std::vector< std::vector<double>* > fPtrVec;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
......
......@@ -46,9 +46,7 @@ class SteppingAction : public G4UserSteppingAction
virtual void UserSteppingAction(const G4Step*);
private:
G4int fScintillationCounter;
G4int fCerenkovCounter;
G4int fEventNumber;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
......
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
/// \file lgAnalysis.hh
/// \brief Selection of the analysis technology
#ifndef lgAnalysis_h
#define lgAnalysis_h 1
#include "g4root.hh"
//#include "g4cvs.hh"
//#include "g4xml.hh"
#endif
......@@ -76,7 +76,7 @@ int main(int argc,char** argv)
G4String macro;
G4String session;
G4String output = "";
G4String output = "", input = "";
#ifdef G4MULTITHREADED
G4int nThreads = 0;
#endif
......@@ -86,6 +86,7 @@ int main(int argc,char** argv)
if ( G4String(argv[i]) == "-m" ) macro = argv[i+1];
else if ( G4String(argv[i]) == "-u" ) session = argv[i+1];
else if ( G4String(argv[i]) == "-o" ) output = argv[i+1];
else if ( G4String(argv[i]) == "-i" ) input = argv[i+1];
else if ( G4String(argv[i]) == "-r" ) myseed = atoi(argv[i+1]);
#ifdef G4MULTITHREADED
else if ( G4String(argv[i]) == "-t" ) {
......@@ -144,16 +145,14 @@ int main(int argc,char** argv)
// Get the pointer to the User Interface manager
//
G4UImanager* UImanager = G4UImanager::GetUIpointer();
if(input != ""){
G4String command = "/Input/FileName ";
UImanager->ApplyCommand(command+input);
}
if ( macro.size() ) {
// Batch mode
G4String command = "/control/execute ";
UImanager->ApplyCommand(command+macro);
PrimaryGeneratorAction* pga = (PrimaryGeneratorAction*)runManager->GetUserPrimaryGeneratorAction();
G4int nEvents = pga->GetnEvents();
if( nEvents > 0){
runManager->BeamOn(nEvents);
}
UImanager->ExecuteMacroFile(macro);
}
else // Define UI session for interactive mode
{
......
Source diff could not be displayed: it is too large. Options to address this: view the blob.
Source diff could not be displayed: it is too large. Options to address this: view the blob.
Source diff could not be displayed: it is too large. Options to address this: view the blob.