Import Geant4 10.6.0.beta source tree

This commit is contained in:
Gabriele Cosmo
2019-06-28 11:59:04 +02:00
parent 28a70706e0
commit d0f911957d
1056 changed files with 95168 additions and 78160 deletions
+108 -1
View File
@@ -19,6 +19,113 @@ committal in the CVS repository !
History file for visualization/modeling
---------------------------------------
13 June 2019 John Allison (modeling-V10-05-04)
- Part of vis-V10-05-20.
- G4ModelingParameters:
o Add cloud to enum options and updated operators != and <<:
o Similarly added to VisAttributesSignifier
- G4PhysicalVolumeModel.cc:
o Handle new VisAttributesSignifiers.
10 June 2019 John Allison (modeling-V10-05-03)
- Part of vis-V10-05-19.
- G4ArrowModel: Further use of const and introduce further protection.
- G4VFieldModel.cc: Further use of const.
29 May 2019 John Allison (modeling-V10-05-02)
- Improve field modelling:
o G4VFieldModel: Improve so even the smallest non-zero sample is visible:
. Values < 10% max are drawn as lines of width 2.
. Values < 1% max have their length fixed at 1% max.
. Reverse colour code. Now, where f = fieldStrength/maxStrength:
0 -> f/2 -> f is coded as red -> green -> blue.
For a uniform field this means arrows are now blue instead of red.
o G4ArrowModel:
. Place checks on dimensions to prevent G4Exceptions in used solids.
. Model arrow head as G4Tet.
- G4PhysicalVolumeModel.cc:
o Improve printing from operator<< for nodeID path.
04 April 2019 John Allison (modeling-V10-05-01)
- Co-works visman-V10-05-04.
- Final (for now) corrections to /vis/viewer/set/sectionPlane.
Still some strange behaviour in small fraction of cases. See
comments in G4PhysicalVolumeModel::DescribeSolid around line 748.
24 March 2019 John Allison (modeling-V10-05-00)
- Fix bug in /vis/viewer/set/sectionPlane.
Involves using G4DisplacedSolid instead of plain G4VSolid.
18 March 2019 Gabriele Cosmo
- Included in vis-V10-05-15
- Corrected few typos comments.
24 February 2019 John Allison
- Included in vis-V10-05-13
- Add constructor to G4PhysicalVolumesSearchScene::Findings from
G4PhysicalVolumeModel::TouchableProperties.
- Fix bug in overlap drawing of parameterised volumes.
19 February 2019 John Allison
- Included in vis-V10-05-12
- Introduced G4BoundingExtentScene. This allows one to accumulate extents
using the newly introduced G4VisExtent::Transform and is a better way
of determining the overall extent of a scene (or of any set of extents)
than by the bounding sphere approach.
- G4VFieldModel, G4ElectricFieldModel, G4MagneticFieldModel:
o Introduced volume for field.
- G4VModel: Introduced GetTransformedExtent. This calculates the extent as
it appears to the user, based on the local extent and the transformation.
- G4PhysicalVolumeModel:
o Use G4BoundingExtentScene instead of G4BoundingSphereScene.
o Fix bug whereby the local extent was incorrectly calculated - in fact
it was the transformed extent. Corresponding corrections to all cases
where the extent is needed, for example, in defining the view
parameters, have been made in this commit.
13 February 2019 John Allison
- Included in vis-V10-05-11
- Implement /vis/set/extentForField - see visualisation/History.
08 February 2019 John Allison
- Included in vis-V10-05-09
- Fix Coverity warnings.
31 January 2019 Michael Kelsey
- Included in vis-V01-05-08
- G4VFieldModel.hh/cc: NEW intermediate base class for magnetic, electric
and gravitational fields. Contains all of DescribeYourselfTo() moved from
G4MagneticFieldModel, plus a pure virtual function (GetFieldAtLocation) to
fetch the field vector (differently by each subclass). Constructor now
takes two strings to let subclasses customize diagnostics and arrow labels.
- G4ElectricFieldModel: NEW concrete class implementing GetFieldAtLocation()
for electric field access.
- G4MagneticFieldModel: Move all of DescribeYourselfTo() to new base class
G4VFieldModel. Implement old contents of "if (field) { ..." block as new
GetFieldAtLocation() function.
29 January 2019 John Allison
- Included in vis-V10-05-06
- G4PhysicalVolumeModel.cc:
o If the top volume is parameterised or a replica describe only one
of them, namely the one specified by the copy number.
26 January 2019 John Allison
- Included in vis-V10-05-06
- Fix calculation of vis extent for parameterisations. This involved
extending G4PhysicalVolumeModel::TouchableProperties to include copy
number and initialising the copy number in the constructor. Then in
G4PhysicalVolumeModel::CalculateExtent solid->ComputeDimensions is
invoked if it is a parameterised volume.
- Some minor tidying.
02 January 2019 John Allison
- Included in vis-V10-05-00.
- G4PhysicalVolumeModel.cc: Add volume count (but comment out printing).
14 November 2018 John Allison (modeling-V10-04-18)
- G4PhysicalVolumeModel.cc: Fix Coverity warning.
@@ -964,7 +1071,7 @@ History file for visualization/modeling
26th January 2006 John Allison (modeling-V08-00-01)
- G4PhysicalVolumeModel: Added capability of maintaining path of the
current drawn (non-culled) volume in terms of drawn (non-culled)
ancesters. See G4PhysicalVolumeModel.hh for detailed description.
ancestors. See G4PhysicalVolumeModel.hh for detailed description.
- Removed some unnecessary data members and other small tidying.
11th January 2006 John Allison (modeling-V08-00-00)
@@ -0,0 +1,69 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
//
//
//
// John Allison 15th February 2019
// An artificial scene to reuse G4VScene code to calculate a bounding extent.
#ifndef G4BOUNDINGEXTENTSCENE_HH
#define G4BOUNDINGEXTENTSCENE_HH
#include "G4PseudoScene.hh"
#include "G4VisExtent.hh"
class G4VModel;
class G4BoundingExtentScene: public G4PseudoScene {
public:
G4BoundingExtentScene (G4VModel* pModel = 0);
virtual ~G4BoundingExtentScene ();
const G4VisExtent& GetExtent () const
{return fExtent;}
const G4VisExtent& GetBoundingExtent () const
{return fExtent;}
////////////////////////////////////////////////////////////////
// The following 2 functions can be used by any code which wishes to
// accrue a bounding sphere. Just instantiate a
// G4BoundingExtentScene and use AccrueBoundingExtent.
void ResetBoundingExtent ();
void AccrueBoundingExtent (const G4VisExtent&);
private:
void ProcessVolume (const G4VSolid& solid);
G4VModel* fpModel;
G4VisExtent fExtent;
};
#endif
@@ -0,0 +1,72 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
//
//
//
// Michael Kelsey 31st January 2019 -- Adapted from new G4MagneticFieldModel
//
// Class Description:
//
// Model that knows how to draw the electric field.
#ifndef G4ELECTRICFIELDMODEL_HH
#define G4ELECTRICFIELDMODEL_HH
#include "G4VFieldModel.hh"
class G4ElectricFieldModel: public G4VFieldModel {
public: // With description
// Constructor just passes through to base
G4ElectricFieldModel
(G4int nDataPointsPerHalfExtent = 3,
Representation representation = Representation::fullArrow,
G4int arrow3DLineSegmentsPerCircle = 6,
const G4VisExtent& extentForField = G4VisExtent(),
const std::vector<G4PhysicalVolumesSearchScene::Findings>& pvFindings
= std::vector<G4PhysicalVolumesSearchScene::Findings>())
: G4VFieldModel
("Electric","E", extentForField, pvFindings,
nDataPointsPerHalfExtent, representation, arrow3DLineSegmentsPerCircle)
{}
virtual ~G4ElectricFieldModel() {;}
protected:
virtual void GetFieldAtLocation(const G4Field* field,
const G4Point3D& position, G4double time,
G4Point3D& result) const;
// The appropriate output from GetFieldValue should be filled into result.
// If (field==0), the function should do nothing; returning without error.
private:
// Private copy contructor and assignment to forbid use...
G4ElectricFieldModel(const G4ElectricFieldModel&);
G4ElectricFieldModel& operator=(const G4ElectricFieldModel&);
};
#endif
@@ -26,7 +26,8 @@
//
//
//
// John Allison 17th August 2013
// John Allison 17th August 2013
// Michael Kelsey 31st January 2019 -- Move functionality to G4VFieldModel
//
// Class Description:
//
@@ -35,40 +36,38 @@
#ifndef G4MAGNETICFIELDMODEL_HH
#define G4MAGNETICFIELDMODEL_HH
#include "G4VModel.hh"
#include "G4VFieldModel.hh"
class G4Colour;
class G4Polyhedron;
class G4MagneticFieldModel: public G4VModel {
public: // With description
enum Representation {fullArrow, lightArrow};
class G4MagneticFieldModel: public G4VFieldModel {
public: // With description
// Constructor just passes through to base
G4MagneticFieldModel
(G4int nDataPointsPerHalfScene = 10,
(G4int nDataPointsPerHalfExtent = 3,
Representation representation = Representation::fullArrow,
G4int arrow3DLineSegmentsPerCircle = 6);
virtual ~G4MagneticFieldModel ();
G4int arrow3DLineSegmentsPerCircle = 6,
const G4VisExtent& extentForField = G4VisExtent(),
const std::vector<G4PhysicalVolumesSearchScene::Findings>& pvFindings
= std::vector<G4PhysicalVolumesSearchScene::Findings>())
: G4VFieldModel
("Magnetic","B", extentForField, pvFindings,
nDataPointsPerHalfExtent, representation, arrow3DLineSegmentsPerCircle)
{}
virtual void DescribeYourselfTo (G4VGraphicsScene&);
// The main task of a model is to describe itself to the graphics scene.
virtual ~G4MagneticFieldModel() {;}
protected:
virtual void GetFieldAtLocation(const G4Field* field,
const G4Point3D& position, G4double time,
G4Point3D& result) const;
// The appropriate output from GetFieldValue should be filled into result.
// If (field==0), the function should do nothing; returning without error.
private:
// Private copy contructor and assignment to forbid use...
G4MagneticFieldModel (const G4MagneticFieldModel&);
G4MagneticFieldModel& operator = (const G4MagneticFieldModel&);
// No. of data points sampled per maximum half scene extent.
// Note that total number of data poinrs sampled can be as high as
// (2*n+1)^3, which can get very big very soon.
G4int fNDataPointsPerMaxHalfScene;
Representation fRepresentation;
G4int fArrow3DLineSegmentsPerCircle;
G4MagneticFieldModel(const G4MagneticFieldModel&);
G4MagneticFieldModel& operator=(const G4MagneticFieldModel&);
};
#endif
@@ -46,6 +46,7 @@
class G4LogicalVolume;
class G4VisAttributes;
class G4VSolid;
class G4DisplacedSolid;
class G4Event;
class G4ModelingParameters {
@@ -57,7 +58,8 @@ public: // With description
wf, // Draw edges - no hidden line removal (wireframe).
hlr, // Draw edges - hidden lines removed.
hsr, // Draw surfaces - hidden surfaces removed.
hlhsr // Draw surfaces and edges - hidden removed.
hlhsr, // Draw surfaces and edges - hidden removed.
cloud // Draw as a cloud of points
};
// enums and nested class for communicating a modification to the vis
@@ -70,6 +72,8 @@ public: // With description
VASLineWidth,
VASForceWireframe,
VASForceSolid,
VASForceCloud,
VASForceNumberOfCloudPoints,
VASForceAuxEdgeVisible,
VASForceLineSegmentsPerCircle
};
@@ -157,6 +161,7 @@ public: // With description
G4bool IsWarning () const;
const G4VisAttributes* GetDefaultVisAttributes () const;
DrawingStyle GetDrawingStyle () const;
G4int GetNumberOfCloudPoints () const;
G4bool IsCulling () const;
G4bool IsCullingInvisible () const;
G4bool IsDensityCulling () const;
@@ -168,8 +173,8 @@ public: // With description
G4double GetExplodeFactor () const;
const G4Point3D& GetExplodeCentre () const;
G4int GetNoOfSides () const;
G4VSolid* GetSectionSolid () const;
G4VSolid* GetCutawaySolid () const;
G4DisplacedSolid* GetSectionSolid () const;
G4DisplacedSolid* GetCutawaySolid () const;
const G4Event* GetEvent () const;
const std::vector<VisAttributesModifier>& GetVisAttributesModifiers() const;
@@ -177,6 +182,7 @@ public: // With description
void SetWarning (G4bool);
void SetDefaultVisAttributes (const G4VisAttributes* pDefaultVisAttributes);
void SetDrawingStyle (DrawingStyle);
void SetNumberOfCloudPoints (G4int);
void SetCulling (G4bool);
void SetCullingInvisible (G4bool);
void SetDensityCulling (G4bool);
@@ -187,8 +193,8 @@ public: // With description
void SetExplodeFactor (G4double explodeFactor);
void SetExplodeCentre (const G4Point3D& explodeCentre);
G4int SetNoOfSides (G4int); // Returns actual number set.
void SetSectionSolid (G4VSolid* pSectionSolid);
void SetCutawaySolid (G4VSolid* pCutawaySolid);
void SetSectionSolid (G4DisplacedSolid* pSectionSolid);
void SetCutawaySolid (G4DisplacedSolid* pCutawaySolid);
void SetEvent (const G4Event* pEvent);
void SetVisAttributesModifiers(const std::vector<VisAttributesModifier>&);
@@ -211,6 +217,8 @@ private:
G4bool fWarning; // Print warnings if true.
const G4VisAttributes* fpDefaultVisAttributes;
DrawingStyle fDrawingStyle; // Drawing style.
G4int fNumberOfCloudPoints; // For drawing in cloud style.
// <= 0 means use viewer default.
G4bool fCulling; // Culling requested.
G4bool fCullInvisible; // Cull (don't Draw) invisible objects.
G4bool fDensityCulling; // Density culling requested. If so...
@@ -221,8 +229,8 @@ private:
G4double fExplodeFactor; // Explode along radius by this factor...
G4Point3D fExplodeCentre; // ...about this centre.
G4int fNoOfSides; // ...if polygon approximates circle.
G4VSolid* fpSectionSolid; // For generic section (DCUT).
G4VSolid* fpCutawaySolid; // For generic cutaways.
G4DisplacedSolid* fpSectionSolid; // For generic section (DCUT).
G4DisplacedSolid* fpCutawaySolid; // For generic cutaways.
const G4Event* fpEvent; // Event being processed.
std::vector<VisAttributesModifier> fVisAttributesModifiers;
};
@@ -43,6 +43,10 @@ G4ModelingParameters::GetDrawingStyle () const {
return fDrawingStyle;
}
inline G4int G4ModelingParameters::GetNumberOfCloudPoints () const {
return fNumberOfCloudPoints;
}
inline G4bool G4ModelingParameters::IsCulling () const {
return fCulling;
}
@@ -87,10 +91,10 @@ inline G4int G4ModelingParameters::GetNoOfSides () const {
return fNoOfSides;
}
inline G4VSolid* G4ModelingParameters::GetSectionSolid () const
inline G4DisplacedSolid* G4ModelingParameters::GetSectionSolid () const
{return fpSectionSolid;}
inline G4VSolid* G4ModelingParameters::GetCutawaySolid () const
inline G4DisplacedSolid* G4ModelingParameters::GetCutawaySolid () const
{return fpCutawaySolid;}
inline const G4Event* G4ModelingParameters::GetEvent () const
@@ -116,6 +120,10 @@ G4ModelingParameters::SetDrawingStyle
fDrawingStyle = style;
}
inline void G4ModelingParameters::SetNumberOfCloudPoints (G4int n) {
fNumberOfCloudPoints = n;
}
inline void G4ModelingParameters::SetCulling (G4bool value) {
fCulling = value;
}
@@ -48,7 +48,7 @@
// number but also by its position in the geometry hierarchy.
//
// It is guaranteed that touchables are presented to the scene handler
// in top-down hierarchy order, i.e., ancesters first, mothers before
// in top-down hierarchy order, i.e., ancestors first, mothers before
// daughters, so the scene handler can be assured that, if it is
// building its own scene graph tree, a mother, if any, will have
// already been encountered and there will already be a node in place
@@ -133,9 +133,10 @@ public: // With description
// Nested struct for encapsulating touchable properties
struct TouchableProperties {
TouchableProperties(): fpTouchablePV(nullptr) {}
TouchableProperties(): fpTouchablePV(nullptr), fCopyNo(0) {}
G4ModelingParameters::PVNameCopyNoPath fTouchablePath;
G4VPhysicalVolume* fpTouchablePV;
G4int fCopyNo;
G4Transform3D fTouchableGlobalTransform;
std::vector<G4PhysicalVolumeNodeID> fTouchableBaseFullPVPath;
};
@@ -204,7 +205,7 @@ public: // With description
const std::vector<G4PhysicalVolumeNodeID>& GetDrawnPVPath() const
{return fDrawnPVPath;}
// Path of the current drawn (non-culled) touchable in terms of
// drawn (non-culled) ancesters. It is a vector of physical volume
// drawn (non-culled) ancestors. It is a vector of physical volume
// node identifiers corresponding to the geometry hierarchy actually
// selected, i.e., with "culled" volumes NOT included.
@@ -28,8 +28,8 @@
//
// John Allison 5th September 2018, based on G4PhysicalVolumeSearchScene
// An artificial scene to find physical volumes. Instead of returning the
// first occurence (G4PhysicalVolumeSearchScene) this class (note the extra
// 's' in the name of this class) returns a vector of all occurences.
// first occurrence (G4PhysicalVolumeSearchScene) this class (note the extra
// 's' in the name of this class) returns a vector of all occurrences.
// It can match a physical volume name with the required match. The latter can
// be of the form "/regexp/", where regexp is a regular expression (see C++
// regex), or a plain string, in which case there must be an exact match.
@@ -70,6 +70,13 @@ public:
, fFoundDepth(foundDepth)
, fFoundBasePVPath(foundBasePVPath)
, fFoundObjectTransformation(foundObjectTransformation) {}
Findings(const G4PhysicalVolumeModel::TouchableProperties& tp)
: fpSearchPV(nullptr)
, fpFoundPV(tp.fpTouchablePV)
, fFoundPVCopyNo(tp.fCopyNo)
, fFoundDepth(0)
, fFoundBasePVPath(tp.fTouchableBaseFullPVPath)
, fFoundObjectTransformation(tp.fTouchableGlobalTransform) {}
G4VPhysicalVolume* fpSearchPV; // Searched physical volume.
G4VPhysicalVolume* fpFoundPV; // Found physical volume.
G4int fFoundPVCopyNo; // Found Copy number.
@@ -0,0 +1,107 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
// Michael Kelsey 31 January 2019
//
// Class Description:
//
// Abstract base class to implement drawing vector field geometries
// (e.g., electric, magnetic or gravity). Implementation extracted
// from G4MagneticFieldModel, with field-value access left pure
// virtual for implementation by base classes.
#ifndef G4VFIELDMODEL_HH
#define G4VFIELDMODEL_HH
#include "G4VModel.hh"
#include "G4Point3D.hh"
#include "G4PhysicalVolumesSearchScene.hh"
#include <vector>
class G4Field;
class G4VFieldModel: public G4VModel {
public: // With description
enum Representation {fullArrow, lightArrow};
G4VFieldModel
(const G4String& typeOfField, const G4String& symbol="",
const G4VisExtent& extentForField = G4VisExtent(),
const std::vector<G4PhysicalVolumesSearchScene::Findings>& pvFindings
= std::vector<G4PhysicalVolumesSearchScene::Findings>(),
G4int nDataPointsPerHalfScene = 10,
Representation representation = Representation::fullArrow,
G4int arrow3DLineSegmentsPerCircle = 6);
// typeOfField is "Electric" or "Magnetic" etc.
// symbol is "E" or "B" etc.
virtual ~G4VFieldModel();
virtual void DescribeYourselfTo(G4VGraphicsScene& sceneHandler);
// The main task of a model is to describe itself to the graphics scene.
// Note: It is in this function that the extent for drawing the filed must
// be calcualted. If fExtentForField is null, pick up the extent from
// the sceneHandler.
protected:
// Subclasses MUST implement this for their particular kind of field
virtual void GetFieldAtLocation(const G4Field* field,
const G4Point3D& position, G4double time,
G4Point3D& result) const = 0;
// The appropriate output from GetFieldValue should be filled into result.
// If (field==0), the function should do nothing; returning without error.
private:
// Private copy contructor and assignment to forbid use...
G4VFieldModel(const G4VFieldModel&);
G4VFieldModel& operator=(const G4VFieldModel&);
G4VisExtent fExtentForField;
// If null, get extent from scene handler in DescribeYourselfTo.
std::vector<G4PhysicalVolumesSearchScene::Findings> fPVFindings;
// If empty, use fExtentForField alone for sampling and drawing.
// If non-empty, use fExtentForField alone for sampling, but only
// draw if sampling point is in the specified physical volume(s).
G4int fNDataPointsPerMaxHalfScene;
// No. of data points sampled per maximum half scene.
// Note that total number of sampling points can be as high as
// (2*n+1)^3, which can get very big. However, fields are usually
// confined to only parts of the scene, so this may not be a problem.
// Sampling can be further limited with fExtentForField and/or fPVFindings.
Representation fRepresentation; // Big arrows or just lines
G4int fArrow3DLineSegmentsPerCircle;
G4String fTypeOfField; // "Electric" or "Magnetic" etc.
G4String fArrowPrefix; // For attaching text label to arrows
};
#endif
@@ -80,6 +80,9 @@ public: // With description
const G4VisExtent& GetExtent () const;
// Extent of visible objects in local coordinate system.
const G4VisExtent& GetTransformedExtent () const;
// Extent of visible objects in transformed coordinate system.
const G4String& GetGlobalDescription () const;
// A description which does not change and lasts the life of the model.
@@ -55,10 +55,12 @@ GEANT4_DEFINE_MODULE(NAME G4modeling
G4AttValueFilterT.hh
G4AttributeFilterT.hh
G4AxesModel.hh
G4BoundingExtentScene.hh
G4BoundingSphereScene.hh
G4CallbackModel.hh
G4DigiFilterFactories.hh
G4DigiModel.hh
G4ElectricFieldModel.hh
G4GPSModel.hh
G4HitFilterFactories.hh
G4HitsModel.hh
@@ -97,6 +99,7 @@ GEANT4_DEFINE_MODULE(NAME G4modeling
G4TrajectoryParticleFilter.hh
G4TrajectoryEncounteredVolumeFilter.hh
G4VAttValueFilter.hh
G4VFieldModel.hh
G4VModel.hh
G4VModel.icc
G4VModelCommand.hh
@@ -108,9 +111,11 @@ GEANT4_DEFINE_MODULE(NAME G4modeling
G4ArrowModel.cc
G4AttFilterUtils.cc
G4AxesModel.cc
G4BoundingExtentScene.cc
G4BoundingSphereScene.cc
G4DigiFilterFactories.cc
G4DigiModel.cc
G4ElectricFieldModel.cc
G4GPSModel.cc
G4HitFilterFactories.cc
G4HitsModel.cc
@@ -141,6 +146,7 @@ GEANT4_DEFINE_MODULE(NAME G4modeling
G4TrajectoryOriginVolumeFilter.cc
G4TrajectoryParticleFilter.cc
G4TrajectoryEncounteredVolumeFilter.cc
G4VFieldModel.cc
G4VModel.cc
G4VTrajectoryModel.cc
G4VisTrajContext.cc
@@ -35,11 +35,12 @@
#include "G4VGraphicsScene.hh"
#include "G4VisAttributes.hh"
#include "G4Tubs.hh"
#include "G4GenericPolycone.hh"
#include "G4Tet.hh"
#include "G4Polyhedron.hh"
#include "G4Vector3D.hh"
#include "G4Point3D.hh"
#include "G4Transform3D.hh"
#include "G4GeometryTolerance.hh"
G4ArrowModel::~G4ArrowModel ()
{
@@ -53,6 +54,8 @@ G4ArrowModel::G4ArrowModel
G4double width, const G4Colour& colour,
const G4String& description,
G4int lineSegmentsPerCircle)
: fpShaftPolyhedron(nullptr)
, fpHeadPolyhedron(nullptr)
{
fType = "G4ArrowModel";
fGlobalTag = fType;
@@ -71,28 +74,33 @@ G4ArrowModel::G4ArrowModel
// Make a cylinder slightly shorter than the arrow length so that it
// doesn't stick out of the head.
const G4double shaftLength = std::sqrt
const G4double tolerance = G4GeometryTolerance::GetInstance()->GetRadialTolerance();
G4double shaftLength = std::sqrt
(std::pow(x2-x1,2)+std::pow(y2-y1,2)+std::pow(z2-z1,2));
if (shaftLength < tolerance) shaftLength = tolerance;
G4double shaftRadius = width/2.;
// Limit the radius
if (shaftRadius > shaftLength/100.) shaftRadius = shaftLength/100.;
if (shaftRadius < tolerance) shaftRadius = tolerance;
const G4double halfShaftLength = shaftLength/2.;
const G4double halfReduction = 4.*shaftRadius;
const G4double halfLength = halfShaftLength-halfReduction;
G4Tubs shaft("shaft",0.,shaftRadius,halfLength,0.,twopi);
G4double halfLength = halfShaftLength - halfReduction;
if (halfLength < tolerance) halfLength = tolerance;
const G4Tubs shaft("shaft",0.,shaftRadius,halfLength,0.,twopi);
fpShaftPolyhedron = shaft.CreatePolyhedron();
// Move it a little so that the tail is at z = -halfShaftLength.
fpShaftPolyhedron->Transform(G4Translate3D(0,0,-halfReduction));
if (fpShaftPolyhedron)
fpShaftPolyhedron->Transform(G4Translate3D(0,0,-halfReduction));
// Locate the head at +halfShaftLength.
const G4int numRZ = 3;
G4double r[] = {0,4,0};
G4double z[] = {0,-6,-4};
for (G4int i = 0; i < numRZ; i++) {
r[i] *= 2.*shaftRadius;
z[i] = halfShaftLength + z[i] * 2.*shaftRadius;
}
G4GenericPolycone head("head",0,twopi,numRZ,r,z);
const G4double zHi = halfShaftLength;
const G4double zLow = halfShaftLength - 12.*shaftRadius;
const G4double rExt = 8. * shaftRadius;
const G4double xExt = std::sqrt(3.)*rExt/2.;
const G4Tet head("head",
G4ThreeVector(0.,0.,zHi),
G4ThreeVector(0.,rExt,zLow),
G4ThreeVector(xExt,-rExt/2.,zLow),
G4ThreeVector(-xExt,-rExt/2.,zLow));
fpHeadPolyhedron = head.CreatePolyhedron();
// Transform to position
@@ -102,14 +110,14 @@ G4ArrowModel::G4ArrowModel
const G4Point3D arrowCentre(0.5*(x1+x2),0.5*(y1+y2),0.5*(z1+z2));
const G4Transform3D tr =
G4Translate3D(arrowCentre) * G4RotateZ3D(phi) * G4RotateY3D(theta);
fpShaftPolyhedron->Transform(tr);
fpHeadPolyhedron->Transform(tr);
if (fpShaftPolyhedron) fpShaftPolyhedron->Transform(tr);
if (fpHeadPolyhedron) fpHeadPolyhedron->Transform(tr);
G4VisAttributes va;
va.SetColour(colour);
va.SetForceSolid(true);
fpShaftPolyhedron->SetVisAttributes(va);
fpHeadPolyhedron->SetVisAttributes(va);
if (fpShaftPolyhedron) fpShaftPolyhedron->SetVisAttributes(va);
if (fpHeadPolyhedron) fpHeadPolyhedron->SetVisAttributes(va);
// Restore number of line segments per circle
G4Polyhedron::SetNumberOfRotationSteps(tempN);
@@ -118,7 +126,7 @@ G4ArrowModel::G4ArrowModel
void G4ArrowModel::DescribeYourselfTo (G4VGraphicsScene& sceneHandler)
{
sceneHandler.BeginPrimitives();
sceneHandler.AddPrimitive(*fpShaftPolyhedron);
sceneHandler.AddPrimitive(*fpHeadPolyhedron);
if (fpShaftPolyhedron) sceneHandler.AddPrimitive(*fpShaftPolyhedron);
if (fpHeadPolyhedron) sceneHandler.AddPrimitive(*fpHeadPolyhedron);
sceneHandler.EndPrimitives();
}
@@ -0,0 +1,80 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
//
//
//
// John Allison 15th February 2019
// An artificial scene to reuse G4VScene code to calculate a bounding extent.
#include "G4BoundingExtentScene.hh"
#include "G4VSolid.hh"
#include "G4PhysicalVolumeModel.hh"
G4BoundingExtentScene::G4BoundingExtentScene (G4VModel* pModel)
:fpModel(pModel)
{}
G4BoundingExtentScene::~G4BoundingExtentScene () {}
void G4BoundingExtentScene::ProcessVolume(const G4VSolid& solid)
{
G4VisExtent newExtent = solid.GetExtent ();
if (fpCurrentObjectTransformation) {
newExtent.Transform (*fpCurrentObjectTransformation);
}
AccrueBoundingExtent (newExtent);
// Curtail descent - can assume daughters are contained within mother...
G4PhysicalVolumeModel* pPVM = dynamic_cast<G4PhysicalVolumeModel*>(fpModel);
if (pPVM) pPVM->CurtailDescent();
}
void G4BoundingExtentScene::ResetBoundingExtent ()
{
fExtent = G4VisExtent();
fpCurrentObjectTransformation = 0;
}
void G4BoundingExtentScene::AccrueBoundingExtent (const G4VisExtent& newExtent)
{
if (fExtent == G4VisExtent()) { // First time.
fExtent = newExtent;
} else {
if (newExtent.GetXmin() < fExtent.GetXmin()) fExtent.SetXmin(newExtent.GetXmin());
if (newExtent.GetYmin() < fExtent.GetYmin()) fExtent.SetYmin(newExtent.GetYmin());
if (newExtent.GetZmin() < fExtent.GetZmin()) fExtent.SetZmin(newExtent.GetZmin());
if (newExtent.GetXmax() > fExtent.GetXmax()) fExtent.SetXmax(newExtent.GetXmax());
if (newExtent.GetYmax() > fExtent.GetYmax()) fExtent.SetYmax(newExtent.GetYmax());
if (newExtent.GetZmax() > fExtent.GetZmax()) fExtent.SetZmax(newExtent.GetZmax());
}
}
@@ -0,0 +1,53 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
//
//
//
// Michael Kelsey 31st January 2019 -- Adapted from new G4MagneticFieldModel
//
// Class Description:
//
// Model that knows how to draw the electric field.
#include "G4ElectricFieldModel.hh"
#include "G4Field.hh"
#include "G4Point3D.hh"
// Return electric field vector for display
void G4ElectricFieldModel::
GetFieldAtLocation(const G4Field* field, const G4Point3D& position,
G4double time, G4Point3D& result) const {
if (!field) return; // No action if no field
G4double xyzt[4] = { position.x(), position.y(), position.z(), time };
G4double BEvals[6] = {0.}; // Field returns {Bx,By,Bz,Ex,Ey,Ez}
field->GetFieldValue(xyzt, BEvals);
result.set(BEvals[3], BEvals[4], BEvals[5]);
return;
}
@@ -34,6 +34,8 @@
#include "G4VSolid.hh"
#include "G4LogicalVolume.hh"
#include "G4PVPlacement.hh"
#include "G4PVParameterised.hh"
#include "G4VPVParameterisation.hh"
#include "G4ModelingParameters.hh"
#include "G4VGraphicsScene.hh"
#include "G4DrawVoxels.hh"
@@ -86,53 +88,35 @@ G4LogicalVolumeModel::G4LogicalVolumeModel
G4LogicalVolumeModel::~G4LogicalVolumeModel () {}
namespace {
// Keep a vector of solid-transform pairs to avoid duplication.
typedef std::pair<G4VSolid*,G4Transform3D> solidTransformPair;
std::vector<solidTransformPair> solidTransformVector;
void drawSolidsAndPoint
// Vis attributes
const G4Colour highlightSolidColour(1.0,0.8,0.8);
const G4double highlightSolidLineWidth(10./*pixels*/);
const G4Colour highlightPointColour(0.5,0.5,1.0);
const G4double highlightPointDiameter(20./*pixels*/);
// Keep a vector of solid-copy number pairs to avoid duplication.
typedef std::pair<G4VSolid*,G4int> solidCopyNoPair;
std::vector<solidCopyNoPair> solidCopyNoVector;
void DrawSolid
(G4VGraphicsScene& sceneHandler,
const G4ThreeVector& point,
G4VSolid* sol1, const G4Transform3D& t1,
G4VSolid* sol2, const G4Transform3D& t2)
{
const G4Colour highlightSolidColour(1.0,0.8,0.8);
const G4double highlightSolidLineWidth(10./*pixels*/);
const G4Colour highlightPointColour(0.5,0.5,1.0);
const G4double highlightPointDiameter(20./*pixels*/);
// Draw first solid. Avoid duplication.
std::pair<G4VSolid*,G4Transform3D> pair1(sol1,t1);
auto iter1 = solidTransformVector.begin();
for ( ; iter1 != solidTransformVector.end(); ++iter1) {
if (iter1->first == pair1.first &&
iter1->second == pair1.second) break;
G4VSolid* sol, G4int copyNo, const G4Transform3D& t) {
// Avoid duplication.
std::pair<G4VSolid*,G4int> pair(sol,copyNo);
auto iter = solidCopyNoVector.begin();
for ( ; iter != solidCopyNoVector.end(); ++iter) {
if (*iter == pair) break;
}
if (iter1 == solidTransformVector.end()) {
solidTransformVector.push_back(pair1);
if (iter == solidCopyNoVector.end()) {
solidCopyNoVector.push_back(pair);
G4VisAttributes highlightSolidVisAtts(highlightSolidColour);
highlightSolidVisAtts.SetLineWidth(highlightSolidLineWidth);
sceneHandler.PreAddSolid(t1,highlightSolidVisAtts);
sceneHandler.AddSolid(*sol1);
sceneHandler.PreAddSolid(t,highlightSolidVisAtts);
sceneHandler.AddSolid(*sol);
sceneHandler.PostAddSolid();
}
// Draw second solid. Avoid duplication.
std::pair<G4VSolid*,G4Transform3D> pair2(sol2,t2);
auto iter2 = solidTransformVector.begin();
for ( ; iter2 != solidTransformVector.end(); ++iter2) {
if (iter2->first == pair2.first &&
iter2->second == pair2.second) break;
}
if (iter2 == solidTransformVector.end()) {
solidTransformVector.push_back(pair2);
G4VisAttributes highlightSolidVisAtts(highlightSolidColour);
highlightSolidVisAtts.SetLineWidth(highlightSolidLineWidth);
sceneHandler.PreAddSolid(t2,highlightSolidVisAtts);
sceneHandler.AddSolid(*sol2);
sceneHandler.PostAddSolid();
}
// Draw points. Draw them all.
}
void DrawPoint
(G4VGraphicsScene& sceneHandler,
const G4ThreeVector& point) {
G4VisAttributes highlightPointVisAtts(highlightPointColour);
G4Circle overlapPoint;
overlapPoint.SetVisAttributes(highlightPointVisAtts);
@@ -207,38 +191,95 @@ void G4LogicalVolumeModel::DescribeYourselfTo
fOverlapsPrinted = true;
}
// Draw overlaps. This algorithm is based on G4PVPlacement::CheckOverlaps.
solidTransformVector.clear();
// Draw overlaps
solidCopyNoVector.clear();
for (G4int iDaughter = 0; iDaughter < nDaughters; ++iDaughter) {
G4VPhysicalVolume* daughterPhys = motherLog->GetDaughter(iDaughter);
// Replicas and paramaterisations not presently processed
if (!dynamic_cast<G4PVPlacement*>(daughterPhys)) continue;
G4AffineTransform tDaughter(daughterPhys->GetRotation(),daughterPhys->GetTranslation());
G4VSolid* daughterSolid = daughterPhys->GetLogicalVolume()->GetSolid();
const G4int nTrials = 1000;
for (G4int i = 0; i < nTrials; ++i) {
G4ThreeVector p = daughterSolid->GetPointOnSurface();
// Transform to mother's coordinate system
G4ThreeVector pMother = tDaughter.TransformPoint(p);
// Check overlaps with the mother volume
if (motherSolid->Inside(pMother)==kOutside) {
// Draw mother and daughter and point
drawSolidsAndPoint
(sceneHandler,pMother,motherSolid,G4Transform3D(),daughterSolid,tDaughter);
G4PVPlacement* daughterPVPlace = dynamic_cast<G4PVPlacement*>(daughterPhys);
G4PVParameterised* daughterPVParam = dynamic_cast<G4PVParameterised*>(daughterPhys);
const G4int nPoints = 1000;
if (daughterPVPlace) {
// This algorithm is based on G4PVPlacement::CheckOverlaps.
G4AffineTransform tDaughter(daughterPhys->GetRotation(),daughterPhys->GetTranslation());
G4VSolid* daughterSolid = daughterPhys->GetLogicalVolume()->GetSolid();
for (G4int i = 0; i < nPoints; ++i) {
G4ThreeVector point = daughterSolid->GetPointOnSurface();
// Transform to mother's coordinate system
G4ThreeVector motherPoint = tDaughter.TransformPoint(point);
// Check overlaps with the mother volume
if (motherSolid->Inside(motherPoint)==kOutside) {
// Draw mother and daughter and point
DrawSolid(sceneHandler,motherSolid,0,G4Transform3D());
DrawSolid(sceneHandler,daughterSolid,daughterPhys->GetCopyNo(),tDaughter);
DrawPoint(sceneHandler,motherPoint);
}
// Check other daughters
for (G4int iSister = 0; iSister < nDaughters; ++iSister) {
if (iSister == iDaughter) continue;
G4VPhysicalVolume* sisterPhys = motherLog->GetDaughter(iSister);
G4AffineTransform tSister(sisterPhys->GetRotation(),sisterPhys->GetTranslation());
// Transform to sister's coordinate system
G4ThreeVector sisterPoint = tSister.InverseTransformPoint(motherPoint);
G4LogicalVolume* sisterLog = sisterPhys->GetLogicalVolume();
G4VSolid* sisterSolid = sisterLog->GetSolid();
if (sisterSolid->Inside(sisterPoint)==kInside) {
// Draw daughter and sister and point
DrawSolid(sceneHandler,daughterSolid,daughterPhys->GetCopyNo(),tDaughter);
DrawSolid(sceneHandler,sisterSolid,sisterPhys->GetCopyNo(),tSister);
DrawPoint(sceneHandler,motherPoint);
}
}
}
// Check other daughters
for (G4int iSister = 0; iSister < nDaughters; ++iSister) {
if (iSister == iDaughter) continue;
G4VPhysicalVolume* sisterPhys = motherLog->GetDaughter(iSister);
G4AffineTransform tSister(sisterPhys->GetRotation(),sisterPhys->GetTranslation());
// Transform to sister's coordinate system
G4ThreeVector pSister = tSister.InverseTransformPoint(pMother);
G4LogicalVolume* sisterLog = sisterPhys->GetLogicalVolume();
G4VSolid* sisterSolid = sisterLog->GetSolid();
if (sisterSolid->Inside(pSister)==kInside) {
// Draw daughter and sister and point
drawSolidsAndPoint
(sceneHandler,pMother,daughterSolid,tDaughter,sisterSolid,tSister);
} else if (daughterPVParam) {
// This algorithm is based on G4PVParameterised::CheckOverlaps
const G4int multiplicity = daughterPVParam->GetMultiplicity();
auto* param = daughterPVParam->GetParameterisation();
// Cache points for later checking against other parameterisations
std::vector<G4ThreeVector> motherPoints;
for (G4int iP = 0; iP < multiplicity; iP++) {
G4VSolid* daughterSolid = param->ComputeSolid(iP, daughterPhys);
daughterSolid->ComputeDimensions(param, iP, daughterPhys);
param->ComputeTransformation(iP, daughterPhys);
G4AffineTransform tDaughter(daughterPVParam->GetRotation(),daughterPVParam->GetTranslation());
for (G4int i = 0; i < nPoints; ++i) {
G4ThreeVector point = daughterSolid->GetPointOnSurface();
// Transform to mother's coordinate system
G4ThreeVector motherPoint = tDaughter.TransformPoint(point);
// Check overlaps with the mother volume
if (motherSolid->Inside(motherPoint)==kOutside) {
// Draw mother and daughter and point
DrawSolid(sceneHandler,motherSolid,0,G4Transform3D());
DrawSolid(sceneHandler,daughterSolid,iP,tDaughter);
DrawPoint(sceneHandler,motherPoint);
}
motherPoints.push_back(motherPoint);
}
// Check sister parameterisations
for (G4int iPP = iP + 1; iPP < multiplicity; iPP++) {
G4VSolid* sisterSolid = param->ComputeSolid(iPP, daughterPhys);
sisterSolid->ComputeDimensions(param, iPP, daughterPhys);
param->ComputeTransformation(iPP, daughterPhys);
G4AffineTransform tSister
(daughterPVParam->GetRotation(),daughterPVParam->GetTranslation());
for (const auto& motherPoint: motherPoints) {
// Transform each point into daughter's frame
G4ThreeVector sisterPoint = tSister.InverseTransformPoint(motherPoint);
if (sisterSolid->Inside(sisterPoint)==kInside) {
// Draw sister
DrawSolid(sceneHandler,sisterSolid,iPP,tSister);
// Recompute daughter parameterisation before drawing
daughterSolid->ComputeDimensions(param, iP, daughterPhys);
param->ComputeTransformation(iP, daughterPhys);
tDaughter = G4AffineTransform
(daughterPVParam->GetRotation(),daughterPVParam->GetTranslation());
DrawSolid(sceneHandler,daughterSolid,iP,tDaughter);
DrawPoint(sceneHandler,motherPoint);
}
}
}
}
}
@@ -27,262 +27,28 @@
//
//
// John Allison 17th August 2013
// Michael Kelsey 31st January 2019 -- Move functionality to G4VFieldModel
//
// Class Description:
//
// Model that knows how to draw the magnetic field.
#include "G4MagneticFieldModel.hh"
#include "G4VGraphicsScene.hh"
#include "G4TransportationManager.hh"
#include "G4FieldManager.hh"
#include "G4Field.hh"
#include "G4Colour.hh"
#include "G4VPhysicalVolume.hh"
#include "G4ArrowModel.hh"
#include "G4Polyline.hh"
#include "G4VisAttributes.hh"
#include "G4SystemOfUnits.hh"
#include "G4Point3D.hh"
#include <sstream>
#include <limits>
#include <vector>
G4MagneticFieldModel::~G4MagneticFieldModel () {}
// Return magnetic field vector for display
G4MagneticFieldModel::G4MagneticFieldModel
(G4int nDataPointsPerMaxHalfScene,
Representation representation,
G4int arrow3DLineSegmentsPerCircle)
: fNDataPointsPerMaxHalfScene(nDataPointsPerMaxHalfScene)
, fRepresentation(representation)
, fArrow3DLineSegmentsPerCircle(arrow3DLineSegmentsPerCircle)
{
fType = "G4MagneticFieldModel";
fGlobalTag = fType;
std::ostringstream oss;
oss << ':' << fNDataPointsPerMaxHalfScene
<< ':' << fArrow3DLineSegmentsPerCircle;
if (fRepresentation == Representation::fullArrow) {
oss << " full arrow";
} else if (fRepresentation == Representation::lightArrow) {
oss << " light arrow";
}
fGlobalDescription = fType + oss.str();
}
void G4MagneticFieldModel::DescribeYourselfTo (G4VGraphicsScene& sceneHandler)
{
// G4cout << "G4MagneticFieldModel::DescribeYourselfTo" << G4endl;
const G4VisExtent& extent = sceneHandler.GetExtent();
const G4double xMin = extent.GetXmin();
const G4double yMin = extent.GetYmin();
const G4double zMin = extent.GetZmin();
const G4double xMax = extent.GetXmax();
const G4double yMax = extent.GetYmax();
const G4double zMax = extent.GetZmax();
const G4double xHalfScene = 0.5 * (xMax - xMin);
const G4double yHalfScene = 0.5 * (yMax - yMin);
const G4double zHalfScene = 0.5 * (zMax - zMin);
const G4double xSceneCentre = 0.5 * (xMax + xMin);
const G4double ySceneCentre = 0.5 * (yMax + yMin);
const G4double zSceneCentre = 0.5 * (zMax + zMin);
const G4double maxHalfScene =
std::max(xHalfScene,std::max(yHalfScene,zHalfScene));
if (maxHalfScene <= 0.) {
G4cout
<< "Extent non-positive."
<< G4endl;
return;
}
G4TransportationManager* tMgr =
G4TransportationManager::GetTransportationManager();
assert(tMgr);
G4Navigator* navigator = tMgr->GetNavigatorForTracking();
assert(navigator);
G4FieldManager* globalFieldMgr = tMgr->GetFieldManager();
const G4Field* globalField = 0;
const G4String intro = "G4MagneticFieldModel::DescribeYourselfTo: ";
if (globalFieldMgr) {
if (globalFieldMgr->DoesFieldExist()) {
globalField = globalFieldMgr->GetDetectorField();
if (!globalField) {
static G4bool warned = false;
if (!warned) {
G4cout << intro
<< "Null global field pointer."
<< G4endl;
warned = true;
}
}
}
} else {
static G4bool warned = false;
if (!warned) {
G4cout << intro
<< "No global field manager."
<< G4endl;
warned = true;
}
}
// Constants
const G4double interval = maxHalfScene / fNDataPointsPerMaxHalfScene;
const G4int nDataPointsPerXHalfScene = G4int(xHalfScene / interval);
const G4int nDataPointsPerYHalfScene = G4int(yHalfScene / interval);
const G4int nDataPointsPerZHalfScene = G4int(zHalfScene / interval);
const G4int nXSamples = 2 * nDataPointsPerXHalfScene + 1;
const G4int nYSamples = 2 * nDataPointsPerYHalfScene + 1;
const G4int nZSamples = 2 * nDataPointsPerZHalfScene + 1;
const G4int nSamples = nXSamples * nYSamples * nZSamples;
const G4int nSamples3 = nSamples * 3;
const G4double arrowLengthMax = 0.8 * interval;
const G4int nResults = 6; // 3 B-field + 3 E-field.
// Working space for GetFieldValue.
double position_time[4] = {0,0,0,0};
double result[nResults];
// Working vectors for field values, etc.
std::vector<G4double> BField(nSamples3); // Initialises to zero.
std::vector<G4double> BFieldMagnitude(nSamples); // Initialises to zero.
std::vector<G4double> xyz(nSamples3); // Initialises to zero.
// Get field values and ascertain maximum field.
G4double BFieldMagnitudeMax = -std::numeric_limits<G4double>::max();
for (G4int i = 0; i < nXSamples; i++) {
G4double x = xSceneCentre + (i - nDataPointsPerXHalfScene) * interval;
position_time[0] = x;
for (G4int j = 0; j < nYSamples; j++) {
G4double y = ySceneCentre + (j - nDataPointsPerYHalfScene) * interval;
position_time[1] = y;
for (G4int k = 0; k < nZSamples; k++) {
G4double z = zSceneCentre + (k - nDataPointsPerZHalfScene) * interval;
position_time[2] = z;
// Calculate indices into working vectors
const G4int ijk = i * nYSamples * nZSamples + j * nZSamples + k;
const G4int ijk3 = ijk * 3;
// Find volume at this location.
G4ThreeVector pos(x,y,z);
const G4VPhysicalVolume* pPV =
navigator->LocateGlobalPointAndSetup(pos,0,false,true);
const G4Field* field = globalField;
if (pPV) {
// Get logical volume.
const G4LogicalVolume* pLV = pPV->GetLogicalVolume();
if (pLV) {
// Value for Region, if any, overrides
G4Region* pRegion = pLV->GetRegion();
if (pRegion) {
G4FieldManager* pRegionFieldMgr = pRegion->GetFieldManager();
if (pRegionFieldMgr) {
field = pRegionFieldMgr->GetDetectorField();
// G4cout << "Region with field" << G4endl;
}
}
// 'Local' value from logical volume, if any, overrides
G4FieldManager* pLVFieldMgr = pLV->GetFieldManager();
if (pLVFieldMgr) {
field = pLVFieldMgr->GetDetectorField();
// G4cout << "Logical volume with field" << G4endl;
}
}
}
// If field found, get values and store in working vectors.
if (field) {
// Get field values in result array.
field->GetFieldValue(position_time,result);
// G4cout
// << "BField/T:"
// << " " << result[0]/tesla
// << " " << result[1]/tesla
// << " " << result[2]/tesla
// << G4endl;
// Store B-field components.
for (G4int l = 0; l < 3; l++) {
BField[ijk3 + l] = result[l];
}
// Calculate magnitude and store.
G4double mag = sqrt
(result[0]*result[0]+result[1]*result[1]+result[2]*result[2]);
BFieldMagnitude[ijk] = mag;
// Store position.
xyz[ijk3] = x;
xyz[ijk3 + 1] = y;
xyz[ijk3 + 2] = z;
// Find maximum field magnitude.
if (mag > BFieldMagnitudeMax) {
BFieldMagnitudeMax = mag;
}
}
}
}
}
if (BFieldMagnitudeMax <= 0) {
G4cout
<< "No field in this scene."
<< G4endl;
return;
}
if (fRepresentation == Representation::lightArrow) sceneHandler.BeginPrimitives();
for (G4int i = 0; i < nSamples; i++) {
if (BFieldMagnitude[i] > 0) {
const G4int i3 = i * 3;
// Field (Bx,By,Bz) at (x,y,z).
const G4double Bx = BField[i3];
const G4double By = BField[i3 + 1];
const G4double Bz = BField[i3 + 2];
const G4double x = xyz[i3];
const G4double y = xyz[i3 + 1];
const G4double z = xyz[i3 + 2];
const G4double B = BFieldMagnitude[i];
// G4cout
// << "Position/mm, BField/T unpacked:"
// << ' ' << x/mm
// << ' ' << y/mm
// << ' ' << z/mm
// << " " << Bx/tesla
// << " " << By/tesla
// << " " << Bz/tesla
// << G4endl;
if (B > 0.) {
const G4double f = B / BFieldMagnitudeMax;
G4double red = 0., green = 0., blue = 0., alpha = 1.;
if (f < 0.5) { // Linear colour scale: 0->0.5->1 is blue->green->red.
green = 2. * f;
blue = 2. * (0.5 - f);
} else {
red = 2. * (f - 0.5);
green = 2. * (1.0 - f);
}
const G4Colour arrowColour(red,green,blue,alpha);
const G4double arrowLength = arrowLengthMax * f;
// Base of arrow is at (x,y,z).
const G4double& x1 = x;
const G4double& y1 = y;
const G4double& z1 = z;
// Head of arrow depends on field direction and strength.
const G4double x2 = x1 + arrowLength * Bx / B;
const G4double y2 = y1 + arrowLength * By / B;
const G4double z2 = z1 + arrowLength * Bz / B;
if (fRepresentation == Representation::fullArrow) {
G4ArrowModel BArrow(x1,y1,z1,x2,y2,z2,arrowLength/5,arrowColour,
"BField",
fArrow3DLineSegmentsPerCircle);
BArrow.DescribeYourselfTo(sceneHandler);
} else if (fRepresentation == Representation::lightArrow) {
G4Polyline BArrowLite;
G4VisAttributes va(arrowColour);
BArrowLite.SetVisAttributes(va);
BArrowLite.push_back(G4Point3D(x1,y1,z1));
BArrowLite.push_back(G4Point3D(x2,y2,z2));
sceneHandler.AddPrimitive(BArrowLite);
}
}
}
}
if (fRepresentation == Representation::lightArrow) sceneHandler.EndPrimitives();
void G4MagneticFieldModel::
GetFieldAtLocation(const G4Field* field, const G4Point3D& position,
G4double time, G4Point3D& result) const {
if (!field) return; // No action if no field
G4double xyzt[4] = { position.x(), position.y(), position.z(), time };
G4double BEvals[6] = {0.}; // Field returns {Bx,By,Bz,Ex,Ey,Ez}
field->GetFieldValue(xyzt, BEvals);
result.set(BEvals[0], BEvals[1], BEvals[2]);
return;
}
@@ -36,6 +36,7 @@
#include "G4ExceptionSeverity.hh"
#include "G4SystemOfUnits.hh"
#include "G4VSolid.hh"
#include "G4DisplacedSolid.hh"
#include "G4VPhysicalVolume.hh"
#include "G4PhysicalVolumeModel.hh"
#include "G4UnitsTable.hh"
@@ -44,6 +45,7 @@ G4ModelingParameters::G4ModelingParameters ():
fWarning (true),
fpDefaultVisAttributes (0),
fDrawingStyle (wf),
fNumberOfCloudPoints (10000),
fCulling (false),
fCullInvisible (false),
fDensityCulling (false),
@@ -70,12 +72,13 @@ G4ModelingParameters::G4ModelingParameters
fWarning (true),
fpDefaultVisAttributes (pDefaultVisAttributes),
fDrawingStyle (drawingStyle),
fNumberOfCloudPoints (10000),
fCulling (isCulling),
fCullInvisible (isCullingInvisible),
fDensityCulling (isDensityCulling),
fVisibleDensity (visibleDensity),
fCullCovered (isCullingCovered),
fCBDAlgorithmNumber(0),
fCBDAlgorithmNumber (0),
fExplodeFactor (1.),
fNoOfSides (noOfSides),
fpSectionSolid (0),
@@ -140,13 +143,13 @@ G4int G4ModelingParameters::SetNoOfSides (G4int nSides) {
}
void G4ModelingParameters::SetSectionSolid
(G4VSolid* pSectionSolid) {
(G4DisplacedSolid* pSectionSolid) {
delete fpSectionSolid;
fpSectionSolid = pSectionSolid;
}
void G4ModelingParameters::SetCutawaySolid
(G4VSolid* pCutawaySolid) {
(G4DisplacedSolid* pCutawaySolid) {
delete fpCutawaySolid;
fpCutawaySolid = pCutawaySolid;
}
@@ -165,17 +168,21 @@ std::ostream& operator << (std::ostream& os, const G4ModelingParameters& mp)
os << "\n Current requested drawing style: ";
switch (mp.fDrawingStyle) {
case G4ModelingParameters::wf:
os << "wireframe"; break;
case G4ModelingParameters::hlr:
os << "hidden line removal (hlr)"; break;
case G4ModelingParameters::hsr:
os << "surface (hsr)"; break;
case G4ModelingParameters::hlhsr:
os << "surface and edges (hlhsr)"; break;
default: os << "unrecognised"; break;
case G4ModelingParameters::wf:
os << "wireframe"; break;
case G4ModelingParameters::hlr:
os << "hidden line removal (hlr)"; break;
case G4ModelingParameters::hsr:
os << "surface (hsr)"; break;
case G4ModelingParameters::hlhsr:
os << "surface and edges (hlhsr)"; break;
case G4ModelingParameters::cloud:
os << "cloud"; break;
default: os << "unrecognised"; break;
}
os << "\n Number of cloud points: " << mp.fNumberOfCloudPoints;
os << "\n Culling: ";
if (mp.fCulling) os << "on";
else os << "off";
@@ -211,11 +218,11 @@ std::ostream& operator << (std::ostream& os, const G4ModelingParameters& mp)
os << "\n No. of sides used in circle polygon approximation: "
<< mp.fNoOfSides;
os << "\n Section (DCUT) shape (G4VSolid) pointer: ";
os << "\n Section (DCUT) shape (G4DisplacedSolid) pointer: ";
if (!mp.fpSectionSolid) os << "non-";
os << "null";
os << "\n Cutaway (DCUT) shape (G4VSolid) pointer: ";
os << "\n Cutaway (DCUT) shape (G4DisplacedSolid) pointer: ";
if (!mp.fpCutawaySolid) os << "non-";
os << "null";
@@ -239,6 +246,8 @@ G4bool G4ModelingParameters::operator !=
if (
(fWarning != mp.fWarning) ||
(*fpDefaultVisAttributes != *mp.fpDefaultVisAttributes) ||
(fDrawingStyle != mp.fDrawingStyle) ||
(fNumberOfCloudPoints != mp.fNumberOfCloudPoints) ||
(fCulling != mp.fCulling) ||
(fCullInvisible != mp.fCullInvisible) ||
(fDensityCulling != mp.fDensityCulling) ||
@@ -295,13 +304,15 @@ G4bool G4ModelingParameters::VisAttributesModifier::operator!=
return true;
break;
case G4ModelingParameters::VASForceWireframe:
case G4ModelingParameters::VASForceSolid:
case G4ModelingParameters::VASForceCloud:
if (fVisAtts.GetForcedDrawingStyle() !=
rhs.fVisAtts.GetForcedDrawingStyle())
return true;
break;
case G4ModelingParameters::VASForceSolid:
if (fVisAtts.GetForcedDrawingStyle() !=
rhs.fVisAtts.GetForcedDrawingStyle())
case G4ModelingParameters::VASForceNumberOfCloudPoints:
if (fVisAtts.GetForcedNumberOfCloudPoints() !=
rhs.fVisAtts.GetForcedNumberOfCloudPoints())
return true;
break;
case G4ModelingParameters::VASForceAuxEdgeVisible:
@@ -331,13 +342,18 @@ G4bool G4ModelingParameters::PVNameCopyNo::operator!=
std::ostream& operator <<
(std::ostream& os, const G4ModelingParameters::PVNameCopyNoPath& path)
{
os << "Touchable path: physical-volume-name:copy-number pairs:\n ";
G4ModelingParameters::PVNameCopyNoPathConstIterator i;
for (i = path.begin(); i != path.end(); ++i) {
if (i != path.begin()) {
os << ',';
os << "Touchable path: ";
if (path.empty()) {
os << "empty";
} else {
os << "physical-volume-name:copy-number pairs:\n ";
G4ModelingParameters::PVNameCopyNoPathConstIterator i;
for (i = path.begin(); i != path.end(); ++i) {
if (i != path.begin()) {
os << ',';
}
os << i->GetName() << ':' << i->GetCopyNo();
}
os << i->GetName() << ':' << i->GetCopyNo();
}
return os;
}
@@ -440,6 +456,20 @@ std::ostream& operator <<
}
}
break;
case G4ModelingParameters::VASForceCloud:
if (vamVisAtts.GetForcedDrawingStyle() == G4VisAttributes::cloud) {
os << " forceCloud ";
if (vamVisAtts.IsForceDrawingStyle()) {
os << "true";
} else {
os << "false";
}
}
break;
case G4ModelingParameters::VASForceNumberOfCloudPoints:
os << " numberOfCloudPoints "
<< vamVisAtts.GetForcedNumberOfCloudPoints();
break;
case G4ModelingParameters::VASForceAuxEdgeVisible:
os << " forceAuxEdgeVisible: ";
if (!vamVisAtts.IsForceDrawingStyle()) {
@@ -40,7 +40,7 @@
#include "G4IntersectionSolid.hh"
#include "G4Material.hh"
#include "G4VisAttributes.hh"
#include "G4BoundingSphereScene.hh"
#include "G4BoundingExtentScene.hh"
#include "G4PhysicalVolumeSearchScene.hh"
#include "G4TransportationManager.hh"
#include "G4Polyhedron.hh"
@@ -54,6 +54,10 @@
#include <sstream>
#include <iomanip>
namespace {
G4int volumeCount = 0;
}
G4PhysicalVolumeModel::G4PhysicalVolumeModel
(G4VPhysicalVolume* pVPV
, G4int requestedDepth
@@ -63,7 +67,7 @@ G4PhysicalVolumeModel::G4PhysicalVolumeModel
, const std::vector<G4PhysicalVolumeNodeID>& baseFullPVPath)
: G4VModel (modelTransformation,pMP)
, fpTopPV (pVPV)
, fTopPVCopyNo (0)
, fTopPVCopyNo (pVPV? pVPV->GetCopyNo(): 0)
, fRequestedDepth (requestedDepth)
, fUseFullExtent (useFullExtent)
, fCurrentDepth (0)
@@ -126,14 +130,26 @@ G4ModelingParameters::PVNameCopyNoPath G4PhysicalVolumeModel::GetPVNameCopyNoPat
void G4PhysicalVolumeModel::CalculateExtent ()
{
// To handle paramaterisations, set copy number and compute dimensions
// to get extent right
G4VPVParameterisation* pP = fpTopPV -> GetParameterisation ();
if (pP) {
fpTopPV -> SetCopyNo (fTopPVCopyNo);
G4VSolid* solid = pP -> ComputeSolid (fTopPVCopyNo, fpTopPV);
solid -> ComputeDimensions (pP, fTopPVCopyNo, fpTopPV);
}
if (fUseFullExtent) {
fExtent = fpTopPV -> GetLogicalVolume () -> GetSolid () -> GetExtent ();
}
else {
G4BoundingSphereScene bsScene(this);
} else {
// Calculate extent of *drawn* volumes, i.e., ignoring culled, e.g.,
// invisible volumes, by traversing the whole geometry hierarchy below
// this physical volume.
G4BoundingExtentScene beScene(this);
const G4int tempRequestedDepth = fRequestedDepth;
fRequestedDepth = -1; // Always search to all depths to define extent.
const G4Transform3D tempTransform = fTransform;
const G4ModelingParameters* tempMP = fpMP;
fRequestedDepth = -1; // Always search to all depths to define extent.
fTransform = G4Transform3D(); // Extent is in local cooridinates
G4ModelingParameters mParams
(0, // No default vis attributes needed.
G4ModelingParameters::wf, // wireframe (not relevant for this).
@@ -144,23 +160,16 @@ void G4PhysicalVolumeModel::CalculateExtent ()
true, // Cull daughters of opaque mothers.
24); // No of sides (not relevant for this operation).
fpMP = &mParams;
DescribeYourselfTo (bsScene);
G4double radius = bsScene.GetRadius();
if (radius < 0.) { // Nothing in the scene.
fExtent = fpTopPV -> GetLogicalVolume () -> GetSolid () -> GetExtent ();
} else {
// Transform back to coordinates relative to the top
// transformation, which is in G4VModel::fTransform. This makes
// it conform to all models, which are defined by a
// transformation and an extent relative to that
// transformation...
G4Point3D centre = bsScene.GetCentre();
centre.transform(fTransform.inverse());
fExtent = G4VisExtent(centre, radius);
}
DescribeYourselfTo (beScene);
fExtent = beScene.GetBoundingExtent();
fpMP = tempMP;
fTransform = tempTransform;
fRequestedDepth = tempRequestedDepth;
}
G4double radius = fExtent.GetExtentRadius();
if (radius < 0.) { // Nothing in the scene - revert to top extent
fExtent = fpTopPV -> GetLogicalVolume () -> GetSolid () -> GetExtent ();
}
}
void G4PhysicalVolumeModel::DescribeYourselfTo
@@ -176,12 +185,19 @@ void G4PhysicalVolumeModel::DescribeYourselfTo
G4Transform3D startingTransformation = fTransform;
volumeCount = 0;
VisitGeometryAndGetVisReps
(fpTopPV,
fRequestedDepth,
startingTransformation,
sceneHandler);
// G4cout
// << "G4PhysicalVolumeModel::DescribeYourselfTo: volume count: "
// << volumeCount
// << G4endl;
// Reset or clear data...
fCurrentDepth = 0;
fpCurrentPV = fpTopPV;
@@ -245,10 +261,15 @@ void G4PhysicalVolumeModel::VisitGeometryAndGetVisReps
G4double offset;
G4bool consuming;
pVPV -> GetReplicationData (axis, nReplicas, width, offset, consuming);
if (fCurrentDepth == 0) nReplicas = 1; // Just draw first
G4int nBegin = 0;
G4int nEnd = nReplicas;
if (fCurrentDepth == 0) { // i.e., top volume
nBegin = fTopPVCopyNo; // Describe only one volume, namely the one
nEnd = nBegin + 1; // specified by the given copy number.
}
G4VPVParameterisation* pP = pVPV -> GetParameterisation ();
if (pP) { // Parametrised volume.
for (int n = 0; n < nReplicas; n++) {
for (int n = nBegin; n < nEnd; n++) {
pSol = pP -> ComputeSolid (n, pVPV);
pP -> ComputeTransformation (n, pVPV);
pSol -> ComputeDimensions (pP, n, pVPV);
@@ -295,7 +316,7 @@ void G4PhysicalVolumeModel::VisitGeometryAndGetVisReps
originalRMax = ((G4Tubs*)pSol)->GetOuterRadius();
}
G4bool visualisable = true;
for (int n = 0; n < nReplicas; n++) {
for (int n = nBegin; n < nEnd; n++) {
G4ThreeVector translation; // Identity.
G4RotationMatrix rotation; // Identity - life enough for visualizing.
G4RotationMatrix* pRotation = 0;
@@ -464,7 +485,7 @@ void G4PhysicalVolumeModel::DescribeAndDescend
// Initialise it with the current vis atts and reset the pointer.
modifiedVisAtts = *pVisAttribs;
pVisAttribs = &modifiedVisAtts;
const G4VisAttributes& transVisAtts = vam.GetVisAttributes();
const G4VisAttributes& transVisAtts = vam.GetVisAttributes();
switch (vam.GetVisAttributesSignifier()) {
case G4ModelingParameters::VASVisibility:
modifiedVisAtts.SetVisibility(transVisAtts.IsVisible());
@@ -498,6 +519,18 @@ void G4PhysicalVolumeModel::DescribeAndDescend
}
}
break;
case G4ModelingParameters::VASForceCloud:
if (transVisAtts.IsForceDrawingStyle()) {
if (transVisAtts.GetForcedDrawingStyle() ==
G4VisAttributes::cloud) {
modifiedVisAtts.SetForceCloud(true);
}
}
break;
case G4ModelingParameters::VASForceNumberOfCloudPoints:
modifiedVisAtts.SetForceNumberOfCloudPoints
(transVisAtts.GetForcedNumberOfCloudPoints());
break;
case G4ModelingParameters::VASForceAuxEdgeVisible:
if (transVisAtts.IsForceAuxEdgeVisible()) {
modifiedVisAtts.SetForceAuxEdgeVisible
@@ -565,6 +598,7 @@ void G4PhysicalVolumeModel::DescribeAndDescend
theNewAT = centering * newTranslation * oldRotation * oldScale;
}
volumeCount++;
DescribeSolid (theNewAT, pSol, pVisAttribs, sceneHandler);
}
@@ -653,14 +687,14 @@ void G4PhysicalVolumeModel::DescribeSolid
const G4VisAttributes* pVisAttribs,
G4VGraphicsScene& sceneHandler)
{
sceneHandler.PreAddSolid (theAT, *pVisAttribs);
G4VSolid* pSectionSolid = fpMP->GetSectionSolid();
G4VSolid* pCutawaySolid = fpMP->GetCutawaySolid();
G4DisplacedSolid* pSectionSolid = fpMP->GetSectionSolid();
G4DisplacedSolid* pCutawaySolid = fpMP->GetCutawaySolid();
if (!fpClippingSolid && !pSectionSolid && !pCutawaySolid) {
sceneHandler.PreAddSolid (theAT, *pVisAttribs);
pSol -> DescribeYourselfTo (sceneHandler); // Standard treatment.
sceneHandler.PostAddSolid ();
} else {
@@ -672,10 +706,10 @@ void G4PhysicalVolumeModel::DescribeSolid
(pVisAttribs->GetForcedLineSegmentsPerCircle());
else
G4Polyhedron::SetNumberOfRotationSteps(fpMP->GetNoOfSides());
const G4Polyhedron* pOriginal = pSol->GetPolyhedron();
const G4Polyhedron* pOriginalPolyhedron = pSol->GetPolyhedron();
G4Polyhedron::ResetNumberOfRotationSteps();
if (!pOriginal) {
if (!pOriginalPolyhedron) {
if (fpMP->IsWarning())
G4cout <<
@@ -687,57 +721,66 @@ void G4PhysicalVolumeModel::DescribeSolid
} else {
G4Polyhedron resultant(*pOriginal);
G4VisAttributes resultantVisAttribs(*pVisAttribs);
G4VSolid* resultantSolid = 0;
G4VSolid* pResultantSolid = 0;
if (fpClippingSolid) {
switch (fClippingMode) {
default:
case subtraction:
resultantSolid = new G4SubtractionSolid
("resultant_solid", pSol, fpClippingSolid, theAT.inverse());
pResultantSolid = new G4SubtractionSolid
("subtracted_clipped_solid", pSol, fpClippingSolid, theAT.inverse());
break;
case intersection:
resultantSolid = new G4IntersectionSolid
("resultant_solid", pSol, fpClippingSolid, theAT.inverse());
pResultantSolid = new G4IntersectionSolid
("intersected_clipped_solid", pSol, fpClippingSolid, theAT.inverse());
break;
}
}
if (pSectionSolid) {
resultantSolid = new G4IntersectionSolid
pResultantSolid = new G4IntersectionSolid
("sectioned_solid", pSol, pSectionSolid, theAT.inverse());
}
if (pCutawaySolid) {
resultantSolid = new G4SubtractionSolid
// Follow above...
pResultantSolid = new G4SubtractionSolid
("cutaway_solid", pSol, pCutawaySolid, theAT.inverse());
}
G4Polyhedron* tmpResultant = resultantSolid->GetPolyhedron();
if (tmpResultant) resultant = *tmpResultant;
else {
if (fpMP->IsWarning())
G4cout <<
"WARNING: G4PhysicalVolumeModel::DescribeSolid: resultant polyhedron for"
"\n solid \"" << pSol->GetName() <<
"\" not defined due to error during Boolean processing."
"\n Original will be drawn in red."
<< G4endl;
resultantVisAttribs.SetColour(G4Colour::Red());
const G4Polyhedron* pResultantPolyhedron = pResultantSolid->GetPolyhedron();
if (!pResultantPolyhedron) {
if (fpMP->IsWarning())
G4cout <<
"WARNING: G4PhysicalVolumeModel::DescribeSolid: resultant polyhedron for"
"\n solid \"" << pSol->GetName() <<
"\" not defined due to error during Boolean processing."
<< G4endl;
} else {
// It seems that if the sectioning solid does not intersect the
// original solid the Boolean Processor returns the original
// polyhedron, or a copy thereof. We do not want it.
// Check the number of facets, etc. If same, ignore.
// What we need from the Boolean Processor is a null pointer or a
// null polyhedron. It seems to return the original or a copy of it.
if (pResultantPolyhedron->GetNoFacets() == pOriginalPolyhedron->GetNoFacets())
// This works in most cases but I still get a box in test202 with
// /vis/viewer/set/sectionPlane on 0 0 0 m 0.1 0.1 1
{
pResultantPolyhedron = nullptr;
}
}
delete resultantSolid;
if (pResultantPolyhedron) {
// Finally, draw polyhedron...
sceneHandler.BeginPrimitives(theAT);
sceneHandler.AddPrimitive(*pResultantPolyhedron);
sceneHandler.EndPrimitives();
}
// Finally, force polyhedron drawing...
resultant.SetVisAttributes(resultantVisAttribs);
sceneHandler.BeginPrimitives(theAT);
sceneHandler.AddPrimitive(resultant);
sceneHandler.EndPrimitives();
delete pResultantSolid;
}
}
sceneHandler.PostAddSolid ();
}
G4bool G4PhysicalVolumeModel::Validate (G4bool warn)
@@ -953,7 +996,7 @@ std::ostream& operator<<
(std::ostream& os, const std::vector<G4PhysicalVolumeModel::G4PhysicalVolumeNodeID>& path)
{
if (path.empty()) {
os << " NULL PATH";
os << " TOP";
} else {
for (const auto& nodeID: path) {
os << ' ' << nodeID;
@@ -28,8 +28,8 @@
//
// John Allison 5th September 2018, based on G4PhysicalVolumeSearchScene
// An artificial scene to find physical volumes. Instead of returning the
// first occurence (G4PhysicalVolumeSearchScene) this class (note the extra
// 's' in the name of this class) returns a vector of all occurences.
// first occurrence (G4PhysicalVolumeSearchScene) this class (note the extra
// 's' in the name of this class) returns a vector of all occurrences.
#include "G4PhysicalVolumesSearchScene.hh"
@@ -49,6 +49,7 @@ void G4PhysicalVolumesSearchScene::ProcessVolume (const G4VSolid&)
G4VPhysicalVolume* pCurrentPV = fpSearchVolumesModel->GetCurrentPV();
const G4String& name = pCurrentPV->GetName();
G4int copyNo = fpSearchVolumesModel->GetCurrentPVCopyNo();
// Match the name with the required physical volume name. The latter can be of
// the form "/regexp/", where regexp is a regular expression (see C++ regex),
// or a plain name, in which case there must be an exact match.
@@ -66,6 +66,7 @@ void G4TouchablePropertiesScene::ProcessVolume (const G4VSolid& /*solid*/) {
if (iNameCopyNo == fRequiredTouchable.end()) {
fFoundTouchableProperties.fTouchablePath = fRequiredTouchable;
fFoundTouchableProperties.fpTouchablePV = fpSearchPVModel->GetCurrentPV();
fFoundTouchableProperties.fCopyNo = fpSearchPVModel->GetCurrentPVCopyNo();
fFoundTouchableProperties.fTouchableGlobalTransform = *fpSearchPVModel->GetCurrentTransform();
fFoundTouchableProperties.fTouchableBaseFullPVPath = fpSearchPVModel->GetFullPVPath();
// Base path is one down from found PV
@@ -0,0 +1,325 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
// Michael Kelsey 31 January 2019
//
// Class Description:
//
// Abstract base class to implement drawing vector field geometries
// (e.g., electric, magnetic or gravity). Implementation extracted
// from G4MagneticFieldModel, with field-value access left pure
// virtual for implementation by base classes.
#include "G4VFieldModel.hh"
#include "G4ArrowModel.hh"
#include "G4Colour.hh"
#include "G4Field.hh"
#include "G4FieldManager.hh"
#include "G4PVPlacement.hh"
#include "G4PVParameterised.hh"
#include "G4Point3D.hh"
#include "G4Polyline.hh"
#include "G4SystemOfUnits.hh"
#include "G4TransportationManager.hh"
#include "G4VGraphicsScene.hh"
#include "G4VPhysicalVolume.hh"
#include "G4VisAttributes.hh"
#include <sstream>
#include <limits>
#include <vector>
// Constructor and destructor
G4VFieldModel::~G4VFieldModel() {;}
G4VFieldModel::G4VFieldModel
(const G4String& typeOfField, const G4String& symbol,
const G4VisExtent& extentForField,
const std::vector<G4PhysicalVolumesSearchScene::Findings>& pvFindings,
G4int nDataPointsPerMaxHalfScene,
Representation representation,
G4int arrow3DLineSegmentsPerCircle)
: fExtentForField(extentForField)
, fPVFindings(pvFindings)
, fNDataPointsPerMaxHalfScene(nDataPointsPerMaxHalfScene)
, fRepresentation(representation)
, fArrow3DLineSegmentsPerCircle(arrow3DLineSegmentsPerCircle)
, fTypeOfField(typeOfField)
, fArrowPrefix(symbol)
{
fType = "G4"+typeOfField+"FieldModel";
fGlobalTag = fType;
std::ostringstream oss;
oss << ':' << fNDataPointsPerMaxHalfScene
<< ':' << fArrow3DLineSegmentsPerCircle;
if (fExtentForField == G4VisExtent::GetNullExtent()) {
oss << " whole scene";
} else {
oss
<< ':' << fExtentForField.GetXmin()
<< ':' << fExtentForField.GetXmax()
<< ':' << fExtentForField.GetYmin()
<< ':' << fExtentForField.GetYmax()
<< ':' << fExtentForField.GetZmin()
<< ':' << fExtentForField.GetZmax();
}
for (const auto& findings: fPVFindings) {
oss
<< ',' << findings.fpFoundPV->GetName()
<< ':' << findings.fFoundPVCopyNo;
}
if (fRepresentation == Representation::fullArrow) {
oss << " full arrow";
} else if (fRepresentation == Representation::lightArrow) {
oss << " light arrow";
}
fGlobalDescription = fType + oss.str();
}
// The main task of a model is to describe itself to the graphics scene.
void G4VFieldModel::DescribeYourselfTo(G4VGraphicsScene& sceneHandler) {
// G4cout << "G4VFieldModel::DescribeYourselfTo" << G4endl;
G4TransportationManager* tMgr =
G4TransportationManager::GetTransportationManager();
assert(tMgr);
G4Navigator* navigator = tMgr->GetNavigatorForTracking();
assert(navigator);
G4FieldManager* globalFieldMgr = tMgr->GetFieldManager();
const G4Field* globalField = 0;
const G4String intro = "G4VFieldModel::DescribeYourselfTo: ";
if (globalFieldMgr) {
if (globalFieldMgr->DoesFieldExist()) {
globalField = globalFieldMgr->GetDetectorField();
if (!globalField) {
static G4bool warned = false;
if (!warned) {
G4cout << intro << "Null global field pointer." << G4endl;
warned = true;
}
}
}
} else {
static G4bool warned = false;
if (!warned) {
G4cout << intro << "No global field manager." << G4endl;
warned = true;
}
}
G4VisExtent sceneExtent = sceneHandler.GetExtent();
const G4double& xMin = sceneExtent.GetXmin();
const G4double& yMin = sceneExtent.GetYmin();
const G4double& zMin = sceneExtent.GetZmin();
const G4double& xMax = sceneExtent.GetXmax();
const G4double& yMax = sceneExtent.GetYmax();
const G4double& zMax = sceneExtent.GetZmax();
const G4double xHalfScene = 0.5 * (xMax - xMin);
const G4double yHalfScene = 0.5 * (yMax - yMin);
const G4double zHalfScene = 0.5 * (zMax - zMin);
const G4double xSceneCentre = 0.5 * (xMax + xMin);
const G4double ySceneCentre = 0.5 * (yMax + yMin);
const G4double zSceneCentre = 0.5 * (zMax + zMin);
const G4double maxHalfScene =
std::max(xHalfScene,std::max(yHalfScene,zHalfScene));
if (maxHalfScene <= 0.) {
G4cout << "Scene extent non-positive." << G4endl;
return;
}
// Constants
const G4double interval = maxHalfScene / fNDataPointsPerMaxHalfScene;
const G4int nDataPointsPerXHalfScene = G4int(xHalfScene / interval);
const G4int nDataPointsPerYHalfScene = G4int(yHalfScene / interval);
const G4int nDataPointsPerZHalfScene = G4int(zHalfScene / interval);
const G4int nXSamples = 2 * nDataPointsPerXHalfScene + 1;
const G4int nYSamples = 2 * nDataPointsPerYHalfScene + 1;
const G4int nZSamples = 2 * nDataPointsPerZHalfScene + 1;
const G4int nSamples = nXSamples * nYSamples * nZSamples;
const G4double arrowLengthMax = 0.8 * interval;
// Working vectors for field values, etc.
std::vector<G4Point3D> Field(nSamples); // Initialises to (0,0,0)
std::vector<G4Point3D> xyz(nSamples); // Initialises to (0,0,0)
G4double FieldMagnitudeMax = -std::numeric_limits<G4double>::max();
// Get field values and ascertain maximum field.
for (G4int i = 0; i < nXSamples; i++) {
G4double x = xSceneCentre + (i - nDataPointsPerXHalfScene) * interval;
for (G4int j = 0; j < nYSamples; j++) {
G4double y = ySceneCentre + (j - nDataPointsPerYHalfScene) * interval;
for (G4int k = 0; k < nZSamples; k++) {
G4double z = zSceneCentre + (k - nDataPointsPerZHalfScene) * interval;
// Calculate indices into working vectors
const G4int ijk = i * nYSamples * nZSamples + j * nZSamples + k;
xyz[ijk].set(x,y,z);
G4ThreeVector pos(x,y,z);
// Check if point is in extent for field
if (fExtentForField != G4VisExtent::GetNullExtent()) {
const auto& ext = fExtentForField; // Alias
if (x < ext.GetXmin() || x > ext.GetXmax() ||
y < ext.GetYmin() || y > ext.GetYmax() ||
z < ext.GetZmin() || z > ext.GetZmax())
continue;
}
// Check if point is in findings
if (!fPVFindings.empty()) {
G4bool isInPV = false;
for (const auto& findings: fPVFindings) {
G4VPhysicalVolume* pv = findings.fpFoundPV;
G4int copyNo = findings.fFoundPVCopyNo;
G4VSolid* solid = pv->GetLogicalVolume()->GetSolid();
G4PVParameterised* pvParam = dynamic_cast<G4PVParameterised*>(pv);
if (pvParam) {
auto* param = pvParam->GetParameterisation();
solid = param->ComputeSolid(copyNo,pvParam);
solid->ComputeDimensions(param,copyNo,pvParam);
}
// Transform point to local coordinate system
const auto& transform = findings.fFoundObjectTransformation;
auto rotation = transform.getRotation();
auto translation = transform.getTranslation();
G4ThreeVector lPos = pos; lPos -= translation; lPos.transform(rotation.invert());
if (solid->Inside(lPos)==kInside) {
isInPV = true;
break;
}
}
if (!isInPV) continue;
}
// Point is in findings - or there were no findings
// Find volume and field at this location.
const G4VPhysicalVolume* pPV =
navigator->LocateGlobalPointAndSetup(pos,0,false,true);
const G4Field* field = globalField;
if (pPV) {
// Get logical volume.
const G4LogicalVolume* pLV = pPV->GetLogicalVolume();
if (pLV) {
// Value for Region, if any, overrides
G4Region* pRegion = pLV->GetRegion();
if (pRegion) {
G4FieldManager* pRegionFieldMgr = pRegion->GetFieldManager();
if (pRegionFieldMgr) {
field = pRegionFieldMgr->GetDetectorField();
// G4cout << "Region with field" << G4endl;
}
}
// 'Local' value from logical volume, if any, overrides
G4FieldManager* pLVFieldMgr = pLV->GetFieldManager();
if (pLVFieldMgr) {
field = pLVFieldMgr->GetDetectorField();
// G4cout << "Logical volume with field" << G4endl;
}
}
}
G4double time = 0.; // FIXME: Can we get event time in some way?
// Subclasses will have implemented this for their own field
GetFieldAtLocation(field, xyz[ijk], time, Field[ijk]);
G4double mag = Field[ijk].mag();
if (mag > FieldMagnitudeMax) FieldMagnitudeMax = mag;
} // for (k, z
} // for (j, y
} // for (i, x
if (FieldMagnitudeMax <= 0.) {
G4cout << "No " << fTypeOfField << " field in this extent." << G4endl;
return;
}
for (G4int i = 0; i < nSamples; i++) {
const G4double Fmag = Field[i].mag();
const G4double f = Fmag / FieldMagnitudeMax;
if (f <= 0.) continue; // Skip zero field locations
G4double red = 0., green = 0., blue = 0., alpha = 1.;
if (f < 0.5) { // Linear colour scale: 0->0.5->1 is red->green->blue.
green = 2. * f;
red = 2. * (0.5 - f);
} else {
blue = 2. * (f - 0.5);
green = 2. * (1.0 - f);
}
const G4Colour arrowColour(red,green,blue,alpha);
// Very small arrows are difficult to see. Better to draw a line.
G4bool drawAsLine = false;
switch (fRepresentation) {
case Representation::fullArrow:
if (f < 0.1) {
drawAsLine = true;
}
break;
case Representation::lightArrow:
drawAsLine = true;
break;
default:
break;
}
// Head of arrow depends on field direction and strength...
G4double arrowLength = arrowLengthMax * f;
// ...but limit the length so it's visible.
if (f < 0.01) arrowLength = arrowLengthMax * 0.01;
const G4Point3D head = xyz[i] + arrowLength*Field[i]/Fmag;
if (drawAsLine) {
G4Polyline FArrowLite;
G4VisAttributes va(arrowColour);
va.SetLineWidth(2.);
FArrowLite.SetVisAttributes(va);
FArrowLite.push_back(xyz[i]);
FArrowLite.push_back(head);
sceneHandler.BeginPrimitives();
sceneHandler.AddPrimitive(FArrowLite);
sceneHandler.EndPrimitives();
} else {
G4ArrowModel FArrow(xyz[i].x(), xyz[i].y(), xyz[i].z(),
head.x(), head.y(), head.z(),
arrowLength/5, arrowColour,
fArrowPrefix+"Field",
fArrow3DLineSegmentsPerCircle);
FArrow.DescribeYourselfTo(sceneHandler);
}
} // for (i, nSamples
}
@@ -55,6 +55,13 @@ G4String G4VModel::GetCurrentDescription () const {
return fGlobalDescription;
}
const G4VisExtent& G4VModel::GetTransformedExtent () const {
static G4VisExtent transformedExtent;
transformedExtent = fExtent;
transformedExtent.Transform(fTransform);
return transformedExtent;
}
G4bool G4VModel::Validate (G4bool) {
return true;
}