Import Geant4 10.6.0.beta source tree
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user