Import Geant4 10.3.0.beta source tree
This commit is contained in:
@@ -0,0 +1,733 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
//
|
||||
// Implementation of G4BoundingEnvelope
|
||||
//
|
||||
// Author: evgueni.tcherniaev@cern.ch
|
||||
//
|
||||
// 2016.05.25 E.Tcherniaev - initial version
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#include <cmath>
|
||||
#include "globals.hh"
|
||||
|
||||
#include "G4BoundingEnvelope.hh"
|
||||
#include "G4GeometryTolerance.hh"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Constructor from an axis aligned bounding box
|
||||
//
|
||||
G4BoundingEnvelope::G4BoundingEnvelope(const G4ThreeVector& pMin,
|
||||
const G4ThreeVector& pMax,
|
||||
G4double delta)
|
||||
{
|
||||
SetDelta(delta);
|
||||
SetBoundingBox(pMin,pMax);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Constructor from a prism
|
||||
//
|
||||
G4BoundingEnvelope::G4BoundingEnvelope(const G4ThreeVectorList& baseA,
|
||||
const G4ThreeVectorList& baseB,
|
||||
G4double delta)
|
||||
{
|
||||
SetDelta(delta);
|
||||
SetBoundingPrism(baseA,baseB);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Constructor from a pyramid
|
||||
//
|
||||
G4BoundingEnvelope::G4BoundingEnvelope(const G4ThreeVector& apex,
|
||||
const G4ThreeVectorList& base,
|
||||
G4double delta)
|
||||
{
|
||||
SetDelta(delta);
|
||||
SetBoundingPyramid(apex,base);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Constructor from a sequence of polygons
|
||||
//
|
||||
G4BoundingEnvelope::G4BoundingEnvelope(
|
||||
const std::vector<G4ThreeVectorList*>& polygons,G4double delta)
|
||||
{
|
||||
SetDelta(delta);
|
||||
SetBoundingPolygons(polygons);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copy constructor
|
||||
//
|
||||
G4BoundingEnvelope::G4BoundingEnvelope(const G4BoundingEnvelope& rhs)
|
||||
: fDelta(rhs.fDelta)
|
||||
{
|
||||
// Copy data
|
||||
G4int nb = rhs.fBases.size();
|
||||
fBases.resize(nb);
|
||||
for (G4int i=0; i<nb; i++) {
|
||||
fBases[i] = new G4Polygon3D(*rhs.fBases[i]);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Assignment operator
|
||||
//
|
||||
G4BoundingEnvelope&
|
||||
G4BoundingEnvelope::operator=(const G4BoundingEnvelope& rhs)
|
||||
{
|
||||
// Check assignment to self
|
||||
if (this == &rhs) { return *this; }
|
||||
|
||||
// Copy data
|
||||
fDelta = rhs.fDelta;
|
||||
CleanPolygons();
|
||||
G4int nb = rhs.fBases.size();
|
||||
fBases.resize(nb);
|
||||
for (G4int i=0; i<nb; i++) {
|
||||
fBases[i] = new G4Polygon3D(*rhs.fBases[i]);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Destructor
|
||||
//
|
||||
G4BoundingEnvelope::~G4BoundingEnvelope()
|
||||
{
|
||||
CleanPolygons();
|
||||
fBases.resize(0);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Set the extension
|
||||
//
|
||||
void G4BoundingEnvelope::SetDelta(G4double delta)
|
||||
{
|
||||
fDelta = std::abs(delta);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Set axis aligned bounding box
|
||||
//
|
||||
void
|
||||
G4BoundingEnvelope::SetBoundingBox(const G4ThreeVector& pMin,
|
||||
const G4ThreeVector& pMax)
|
||||
{
|
||||
// Check parameters
|
||||
if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Badly defined bounding box (min >= max)!"
|
||||
<< "\npMin = " << pMin
|
||||
<< "\npMax = " << pMax;
|
||||
G4Exception("G4BoundingEnvelope::SetBoundingBox()",
|
||||
"GeomMgt0001", FatalException, message);
|
||||
}
|
||||
|
||||
CleanPolygons();
|
||||
fBases.resize(2);
|
||||
|
||||
// Set 1st base
|
||||
fBases[0] = new G4Polygon3D(4);
|
||||
(*fBases[0])[0] = G4Point3D(pMin.x(),pMin.y(),pMin.z());
|
||||
(*fBases[0])[1] = G4Point3D(pMax.x(),pMin.y(),pMin.z());
|
||||
(*fBases[0])[2] = G4Point3D(pMax.x(),pMax.y(),pMin.z());
|
||||
(*fBases[0])[3] = G4Point3D(pMin.x(),pMax.y(),pMin.z());
|
||||
|
||||
// Set 2nd base
|
||||
fBases[1] = new G4Polygon3D(4);
|
||||
(*fBases[1])[0] = G4Point3D(pMin.x(),pMin.y(),pMax.z());
|
||||
(*fBases[1])[1] = G4Point3D(pMax.x(),pMin.y(),pMax.z());
|
||||
(*fBases[1])[2] = G4Point3D(pMax.x(),pMax.y(),pMax.z());
|
||||
(*fBases[1])[3] = G4Point3D(pMin.x(),pMax.y(),pMax.z());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Set bounding prism
|
||||
//
|
||||
void
|
||||
G4BoundingEnvelope::SetBoundingPrism(const G4ThreeVectorList& baseA,
|
||||
const G4ThreeVectorList& baseB)
|
||||
{
|
||||
G4int na = baseA.size();
|
||||
G4int nb = baseB.size();
|
||||
if (na < 3 || nb < 3 || na != nb)
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Badly defined bases of the bounding prism!"
|
||||
<< "\nNumber of vertices in 1st base: " << na
|
||||
<< "\nNumber of vertices in 2nd base: " << nb;
|
||||
G4Exception("G4BoundingEnvelope::SetBoundingPrism()",
|
||||
"GeomMgt0001", FatalException, message);
|
||||
}
|
||||
|
||||
CleanPolygons();
|
||||
fBases.resize(2);
|
||||
|
||||
// Set 1st base
|
||||
fBases[0] = new G4Polygon3D(na);
|
||||
for (G4int i=0; i<na; i++) (*fBases[0])[i] = baseA[i];
|
||||
|
||||
// Set 2nd base
|
||||
fBases[1] = new G4Polygon3D(nb);
|
||||
for (G4int i=0; i<nb; i++) (*fBases[1])[i] = baseB[i];
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Set bounding pyramid
|
||||
//
|
||||
void
|
||||
G4BoundingEnvelope::SetBoundingPyramid(const G4ThreeVector& apex,
|
||||
const G4ThreeVectorList& base)
|
||||
{
|
||||
// Check parameters
|
||||
G4int np = base.size();
|
||||
if (np < 3)
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Badly defined base of the bounding pyramid!"
|
||||
<< "\nNumber of vertices in the base: " << np;
|
||||
G4Exception("G4BoundingEnvelope::SetBoundingPyramid()",
|
||||
"GeomMgt0001", FatalException, message);
|
||||
}
|
||||
|
||||
CleanPolygons();
|
||||
fBases.resize(2);
|
||||
|
||||
// Set apex
|
||||
fBases[0] = new G4Polygon3D(1);
|
||||
(*fBases[0])[0] = apex;
|
||||
|
||||
// Set base
|
||||
fBases[1] = new G4Polygon3D(np);
|
||||
for (G4int i=0; i<np; i++) (*fBases[1])[i] = base[i];
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Set bounding sequence of polygons.
|
||||
// Firsf and last polygons may consist of a single vertex
|
||||
//
|
||||
void G4BoundingEnvelope::SetBoundingPolygons(
|
||||
const std::vector<G4ThreeVectorList*>& polygons)
|
||||
{
|
||||
// Check parameters
|
||||
G4int nbases = polygons.size();
|
||||
if (nbases < 2)
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Wrong number of polygons in the sequence: " << nbases
|
||||
<< "\nShould be at least two!";
|
||||
G4Exception("G4BoundingEnvelope::SetBoundingPolygons()",
|
||||
"GeomMgt0001", FatalException, message);
|
||||
return;
|
||||
}
|
||||
|
||||
G4int nsize = std::max(polygons[0]->size(),polygons[1]->size());
|
||||
if (nsize < 3) {
|
||||
std::ostringstream message;
|
||||
message << "Badly constructed polygons!"
|
||||
<< "\nNumber of polygons: " << nbases
|
||||
<< "\nPolygon #0 size: " << polygons[0]->size()
|
||||
<< "\nPolygon #1 size: " << polygons[1]->size()
|
||||
<< "\n...";
|
||||
G4Exception("G4BoundingEnvelope::SetBoundingPolygons()",
|
||||
"GeomMgt0001", FatalException, message);
|
||||
return;
|
||||
}
|
||||
|
||||
for (G4int k=0; k<nbases; k++) {
|
||||
G4int np = polygons[k]->size();
|
||||
if (np == nsize) continue;
|
||||
if (np == 1 && k==0) continue;
|
||||
if (np == 1 && k==nbases) continue;
|
||||
std::ostringstream message;
|
||||
message << "Badly constructed polygons!"
|
||||
<< "\nNumber of polygons: " << nbases
|
||||
<< "\nPolygon #" << k << " size: " << np
|
||||
<< "\nexpected size: " << nsize;
|
||||
G4Exception("G4BoundingEnvelope::SetBoundingPolygons()",
|
||||
"GeomMgt0001", FatalException, message);
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy polygons
|
||||
CleanPolygons();
|
||||
fBases.resize(nbases);
|
||||
for (G4int k=0; k<nbases; k++) {
|
||||
G4int np = polygons[k]->size();
|
||||
fBases[k] = new G4Polygon3D(np);
|
||||
for (G4int i=0; i<np; i++) (*fBases[k])[i] = (*polygons[k])[i];
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Free memory allocated for polygons
|
||||
//
|
||||
void G4BoundingEnvelope::CleanPolygons()
|
||||
{
|
||||
G4int nb = fBases.size();
|
||||
for (G4int i=0; i<nb; i++) {
|
||||
delete fBases[i]; fBases[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Calculate extent of the specified bounding envelope
|
||||
//
|
||||
G4bool
|
||||
G4BoundingEnvelope::CalculateExtent(const EAxis pAxis,
|
||||
const G4VoxelLimits& pVoxelLimits,
|
||||
const G4Transform3D& pTransform3D,
|
||||
G4double& pMin, G4double& pMax) const
|
||||
{
|
||||
// Create adjusted G4VoxelLimits box. New limits are extended by
|
||||
// fDelta multiplied by max scale factor of the transformation.
|
||||
//
|
||||
G4Scale3D scale3D; G4Rotate3D rotate3D; G4Translate3D translate3D;
|
||||
pTransform3D.getDecomposition(scale3D, rotate3D, translate3D);
|
||||
G4double scale = std::max(std::max(std::abs(scale3D.xx()),
|
||||
std::abs(scale3D.yy())),
|
||||
std::abs(scale3D.zz()));
|
||||
G4double delta = (scale > 1.) ? fDelta*scale : fDelta;
|
||||
G4VoxelLimits limits = GetAdjustedVoxelLimits(pVoxelLimits, delta);
|
||||
|
||||
// Main loop along the set of prisms
|
||||
//
|
||||
G4Segment3D extent(G4Point3D( kInfinity, kInfinity, kInfinity),
|
||||
G4Point3D(-kInfinity,-kInfinity,-kInfinity));
|
||||
|
||||
G4int nbases = fBases.size();
|
||||
for (G4int k=0; k<nbases-1; k++)
|
||||
{
|
||||
// Transform vertices of and find bounding box of current prism
|
||||
G4Polygon3D baseA, baseB;
|
||||
G4Segment3D prismAABB(G4Point3D( kInfinity, kInfinity, kInfinity),
|
||||
G4Point3D(-kInfinity,-kInfinity,-kInfinity));
|
||||
|
||||
TransformVertices(pTransform3D, *fBases[k] , baseA, prismAABB);
|
||||
TransformVertices(pTransform3D, *fBases[k+1], baseB, prismAABB);
|
||||
|
||||
// Check that bounding box of the prism intersect the voxel limits
|
||||
if (prismAABB.first.x() > limits.GetMaxXExtent()) continue;
|
||||
if (prismAABB.first.y() > limits.GetMaxYExtent()) continue;
|
||||
if (prismAABB.first.z() > limits.GetMaxZExtent()) continue;
|
||||
if (prismAABB.second.x() < limits.GetMinXExtent()) continue;
|
||||
if (prismAABB.second.y() < limits.GetMinYExtent()) continue;
|
||||
if (prismAABB.second.z() < limits.GetMinZExtent()) continue;
|
||||
|
||||
// Clip edges of the prism by adjusted G4VoxelLimits box
|
||||
std::vector<G4Segment3D> vecEdges;
|
||||
CreateListOfEdges(baseA, baseB, vecEdges);
|
||||
if (ClipEdgesByVoxelLimits(vecEdges, limits, extent)) continue;
|
||||
|
||||
// Some edges of the prism are completely outside of the voxel
|
||||
// limits, clip edges of adjusted G4VoxelLimits box by the prism
|
||||
std::vector<G4Plane3D> vecPlanes;
|
||||
CreateListOfPlanes(baseA, baseB, vecPlanes);
|
||||
ClipVoxelLimitsByPlanes(limits, vecPlanes, prismAABB, extent);
|
||||
}
|
||||
|
||||
// Final adjustment of the extent
|
||||
//
|
||||
G4double emin=kInfinity, emax=kInfinity;
|
||||
if (pAxis == kXAxis) { emin = extent.first.x(); emax = extent.second.x(); }
|
||||
if (pAxis == kYAxis) { emin = extent.first.y(); emax = extent.second.y(); }
|
||||
if (pAxis == kZAxis) { emin = extent.first.z(); emax = extent.second.z(); }
|
||||
|
||||
G4bool exist = false;
|
||||
if (emin <= emax) {
|
||||
exist = true;
|
||||
// Add the extension to the endpoints
|
||||
if (emin > limits.GetMinExtent(pAxis)) emin -= delta;
|
||||
if (emax < limits.GetMaxExtent(pAxis)) emax += delta;
|
||||
|
||||
G4double kCarTolerance =
|
||||
G4GeometryTolerance::GetInstance()->GetSurfaceTolerance();
|
||||
|
||||
// Clip by original voxel limits, if required
|
||||
if (emin <= pVoxelLimits.GetMinExtent(pAxis)) {
|
||||
pMin = pVoxelLimits.GetMinExtent(pAxis) - kCarTolerance;
|
||||
} else {
|
||||
pMin = emin;
|
||||
}
|
||||
if (emax >= pVoxelLimits.GetMaxExtent(pAxis)) {
|
||||
pMax = pVoxelLimits.GetMaxExtent(pAxis) + kCarTolerance;
|
||||
} else {
|
||||
pMax = emax;
|
||||
}
|
||||
exist = true;
|
||||
} else {
|
||||
exist = false;
|
||||
pMin = kInfinity;
|
||||
pMax = -kInfinity;
|
||||
}
|
||||
|
||||
return exist;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Create adjusted voxel limits
|
||||
//
|
||||
G4VoxelLimits
|
||||
G4BoundingEnvelope::GetAdjustedVoxelLimits(const G4VoxelLimits& pVoxelLimits,
|
||||
G4double pDelta) const
|
||||
{
|
||||
EAxis axis[] = { kXAxis,kYAxis,kZAxis };
|
||||
G4VoxelLimits limits; // default is unlimited
|
||||
for (G4int i=0; i<3; i++) {
|
||||
if (pVoxelLimits.IsLimited(axis[i])) {
|
||||
G4double emin = pVoxelLimits.GetMinExtent(axis[i]) - pDelta;
|
||||
G4double emax = pVoxelLimits.GetMaxExtent(axis[i]) + pDelta;
|
||||
limits.AddLimit(axis[i], emin, emax);
|
||||
}
|
||||
}
|
||||
return limits;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Transform vertices of a polygon and update the bounding box
|
||||
//
|
||||
void
|
||||
G4BoundingEnvelope::TransformVertices(const G4Transform3D& pTransform3D,
|
||||
const G4Polygon3D& polyA,
|
||||
G4Polygon3D& polyB,
|
||||
G4Segment3D& pAABB) const
|
||||
{
|
||||
G4double xmin = pAABB.first.x();
|
||||
G4double ymin = pAABB.first.y();
|
||||
G4double zmin = pAABB.first.z();
|
||||
G4double xmax = pAABB.second.x();
|
||||
G4double ymax = pAABB.second.y();
|
||||
G4double zmax = pAABB.second.z();
|
||||
|
||||
G4int np = polyA.size();
|
||||
polyB.resize(np);
|
||||
for (G4int i=0; i<np; i++) {
|
||||
polyB[i] = pTransform3D*polyA[i];
|
||||
xmin = std::min(xmin,polyB[i].x());
|
||||
ymin = std::min(ymin,polyB[i].y());
|
||||
zmin = std::min(zmin,polyB[i].z());
|
||||
xmax = std::max(xmax,polyB[i].x());
|
||||
ymax = std::max(ymax,polyB[i].y());
|
||||
zmax = std::max(zmax,polyB[i].z());
|
||||
}
|
||||
|
||||
pAABB.first.set( xmin,ymin,zmin);
|
||||
pAABB.second.set(xmax,ymax,zmax);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Create list of edges of a prism
|
||||
//
|
||||
void
|
||||
G4BoundingEnvelope::CreateListOfEdges(const G4Polygon3D& baseA,
|
||||
const G4Polygon3D& baseB,
|
||||
std::vector<G4Segment3D>& pEdges) const
|
||||
{
|
||||
G4int na = baseA.size();
|
||||
G4int nb = baseB.size();
|
||||
pEdges.resize(0);
|
||||
if (na == nb) {
|
||||
G4int k = na - 1;
|
||||
for (G4int i=0; i<na; i++) {
|
||||
pEdges.push_back(G4Segment3D(baseA[i],baseB[i]));
|
||||
pEdges.push_back(G4Segment3D(baseA[i],baseA[k]));
|
||||
pEdges.push_back(G4Segment3D(baseB[i],baseB[k]));
|
||||
k = i;
|
||||
}
|
||||
} else if (nb == 1) {
|
||||
G4int k = na - 1;
|
||||
for (G4int i=0; i<na; i++) {
|
||||
pEdges.push_back(G4Segment3D(baseA[i],baseA[k]));
|
||||
pEdges.push_back(G4Segment3D(baseA[i],baseB[0]));
|
||||
k = i;
|
||||
}
|
||||
} else if (na == 1) {
|
||||
G4int k = nb - 1;
|
||||
for (G4int i=0; i<nb; i++) {
|
||||
pEdges.push_back(G4Segment3D(baseB[i],baseB[k]));
|
||||
pEdges.push_back(G4Segment3D(baseB[i],baseA[0]));
|
||||
k = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Create list of planes bounding a prism
|
||||
//
|
||||
void
|
||||
G4BoundingEnvelope::CreateListOfPlanes(const G4Polygon3D& baseA,
|
||||
const G4Polygon3D& baseB,
|
||||
std::vector<G4Plane3D>& pPlanes) const
|
||||
{
|
||||
// Find centers of the bases and internal point of the prism
|
||||
//
|
||||
G4int na = baseA.size();
|
||||
G4int nb = baseB.size();
|
||||
G4Point3D pa(0.,0.,0.), pb(0.,0.,0.), p0;
|
||||
for (G4int i=0; i<na; i++) pa += baseA[i];
|
||||
for (G4int i=0; i<nb; i++) pb += baseB[i];
|
||||
pa /= na; pb /= nb; p0 = (pa+pb)/2.;
|
||||
|
||||
// Create list of planes
|
||||
//
|
||||
pPlanes.resize(0);
|
||||
if (na == nb) {
|
||||
G4int k = na - 1;
|
||||
for (G4int i=0; i<na; i++) {
|
||||
pPlanes.push_back(G4Plane3D(baseA[i],baseA[k],baseB[k]));
|
||||
k = i;
|
||||
}
|
||||
pPlanes.push_back(G4Plane3D(baseA[1],baseA[0],pa));
|
||||
pPlanes.push_back(G4Plane3D(baseB[0],baseB[1],pb));
|
||||
} else if (nb == 1) {
|
||||
G4int k = na - 1;
|
||||
for (G4int i=0; i<na; i++) {
|
||||
pPlanes.push_back(G4Plane3D(baseA[i],baseA[k],baseB[0]));
|
||||
k = i;
|
||||
}
|
||||
pPlanes.push_back(G4Plane3D(baseA[2],baseA[1],baseA[0]));
|
||||
} else if (na == 1) {
|
||||
G4int k = nb - 1;
|
||||
for (G4int i=0; i<nb; i++) {
|
||||
pPlanes.push_back(G4Plane3D(baseB[k],baseB[i],baseA[0]));
|
||||
k = i;
|
||||
}
|
||||
pPlanes.push_back(G4Plane3D(baseB[0],baseB[1],baseB[2]));
|
||||
}
|
||||
|
||||
// Ensure that normals of the planes point to outside
|
||||
//
|
||||
G4int nplanes = pPlanes.size();
|
||||
for (G4int i=0; i<nplanes; i++) {
|
||||
pPlanes[i].normalize();
|
||||
if (pPlanes[i].distance(p0) > 0) {
|
||||
pPlanes[i] = G4Plane3D(-pPlanes[i].a(),-pPlanes[i].b(),
|
||||
-pPlanes[i].c(),-pPlanes[i].d());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Clip edges of a prism by G4VoxelLimits box
|
||||
//
|
||||
G4bool
|
||||
G4BoundingEnvelope::ClipEdgesByVoxelLimits(const std::vector<G4Segment3D>& pEdges,
|
||||
const G4VoxelLimits& pBox,
|
||||
G4Segment3D& pExtent) const
|
||||
{
|
||||
G4bool done = true;
|
||||
G4Point3D emin = pExtent.first;
|
||||
G4Point3D emax = pExtent.second;
|
||||
|
||||
G4int nedges = pEdges.size();
|
||||
for (G4int k=0; k<nedges; k++)
|
||||
{
|
||||
G4double d1, d2;
|
||||
G4Point3D p1 = pEdges[k].first;
|
||||
G4Point3D p2 = pEdges[k].second;
|
||||
|
||||
// Clip current edge by X min
|
||||
d1 = pBox.GetMinXExtent() - p1.x();
|
||||
d2 = pBox.GetMinXExtent() - p2.x();
|
||||
if (d1 > 0.0) {
|
||||
if (d2 > 0.0) { done = false; continue; } // go to next edge
|
||||
p1 = (p2*d1-p1*d2)/(d1-d2); // move p1
|
||||
} else {
|
||||
if (d2 > 0.0) { p2 = (p1*d2-p2*d1)/(d2-d1); } // move p2
|
||||
}
|
||||
|
||||
// Clip current edge by X max
|
||||
d1 = p1.x() - pBox.GetMaxXExtent();
|
||||
d2 = p2.x() - pBox.GetMaxXExtent();
|
||||
if (d1 > 0.) {
|
||||
if (d2 > 0.) { done = false; continue; } // go to next edge
|
||||
p1 = (p2*d1-p1*d2)/(d1-d2);
|
||||
} else {
|
||||
if (d2 > 0.) { p2 = (p1*d2-p2*d1)/(d2-d1); }
|
||||
}
|
||||
|
||||
// Clip current edge by Y min
|
||||
d1 = pBox.GetMinYExtent() - p1.y();
|
||||
d2 = pBox.GetMinYExtent() - p2.y();
|
||||
if (d1 > 0.) {
|
||||
if (d2 > 0.) { done = false; continue; } // go to next edge
|
||||
p1 = (p2*d1-p1*d2)/(d1-d2);
|
||||
} else {
|
||||
if (d2 > 0.) { p2 = (p1*d2-p2*d1)/(d2-d1); }
|
||||
}
|
||||
|
||||
// Clip current edge by Y max
|
||||
d1 = p1.y() - pBox.GetMaxYExtent();
|
||||
d2 = p2.y() - pBox.GetMaxYExtent();
|
||||
if (d1 > 0.) {
|
||||
if (d2 > 0.) { done = false; continue; } // go to next edge
|
||||
p1 = (p2*d1-p1*d2)/(d1-d2);
|
||||
} else {
|
||||
if (d2 > 0.) { p2 = (p1*d2-p2*d1)/(d2-d1); }
|
||||
}
|
||||
|
||||
// Clip current edge by Z min
|
||||
d1 = pBox.GetMinZExtent() - p1.z();
|
||||
d2 = pBox.GetMinZExtent() - p2.z();
|
||||
if (d1 > 0.) {
|
||||
if (d2 > 0.) { done = false; continue; } // go to next edge
|
||||
p1 = (p2*d1-p1*d2)/(d1-d2);
|
||||
} else {
|
||||
if (d2 > 0.) { p2 = (p1*d2-p2*d1)/(d2-d1); }
|
||||
}
|
||||
|
||||
// Clip current edge by Z max
|
||||
d1 = p1.z() - pBox.GetMaxZExtent();
|
||||
d2 = p2.z() - pBox.GetMaxZExtent();
|
||||
if (d1 > 0.) {
|
||||
if (d2 > 0.) { done = false; continue; } // go to next edge
|
||||
p1 = (p2*d1-p1*d2)/(d1-d2);
|
||||
} else {
|
||||
if (d2 > 0.) { p2 = (p1*d2-p2*d1)/(d2-d1); }
|
||||
}
|
||||
|
||||
// Adjust current extent
|
||||
emin.setX(std::min(std::min(p1.x(),p2.x()),emin.x()));
|
||||
emin.setY(std::min(std::min(p1.y(),p2.y()),emin.y()));
|
||||
emin.setZ(std::min(std::min(p1.z(),p2.z()),emin.z()));
|
||||
|
||||
emax.setX(std::max(std::max(p1.x(),p2.x()),emax.x()));
|
||||
emax.setY(std::max(std::max(p1.y(),p2.y()),emax.y()));
|
||||
emax.setZ(std::max(std::max(p1.z(),p2.z()),emax.z()));
|
||||
}
|
||||
|
||||
// Return true if all edges (at least partially) are inside
|
||||
// the voxel limits, otherwise return false
|
||||
pExtent.first = emin;
|
||||
pExtent.second = emax;
|
||||
return done;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Clip G4VoxelLimits by set of planes bounding a convex prism
|
||||
//
|
||||
void
|
||||
G4BoundingEnvelope::ClipVoxelLimitsByPlanes(const G4VoxelLimits& pBox,
|
||||
const std::vector<G4Plane3D>& pPlanes,
|
||||
const G4Segment3D& pAABB,
|
||||
G4Segment3D& pExtent) const
|
||||
{
|
||||
G4Point3D emin = pExtent.first;
|
||||
G4Point3D emax = pExtent.second;
|
||||
|
||||
// Create 12 edges of the voxel limits box, reduce them where
|
||||
// appropriate to avoid calculations with big numbers (kInfinity)
|
||||
//
|
||||
G4double xmin = pBox.GetMinXExtent(), xmax = pBox.GetMaxXExtent();
|
||||
G4double ymin = pBox.GetMinYExtent(), ymax = pBox.GetMaxYExtent();
|
||||
G4double zmin = pBox.GetMinZExtent(), zmax = pBox.GetMaxZExtent();
|
||||
if( xmin < 2.*pAABB.first.x() && xmax > 2.*pAABB.second.x())
|
||||
{ xmin = 2.*pAABB.first.x(); xmax = 2.*pAABB.second.x(); }
|
||||
if( ymin < 2.*pAABB.first.y() && ymax > 2.*pAABB.second.y())
|
||||
{ ymin = 2.*pAABB.first.y(); ymax = 2.*pAABB.second.y(); }
|
||||
if( zmin < 2.*pAABB.first.z() && zmax > 2.*pAABB.second.z())
|
||||
{ zmin = 2.*pAABB.first.z(); zmax = 2.*pAABB.second.z(); }
|
||||
|
||||
std::vector<G4Segment3D> edges(12);
|
||||
edges[0].first.set(xmin,ymin,zmin); edges[0].second.set(xmax,ymin,zmin);
|
||||
edges[1].first = edges[0].second; edges[1].second.set(xmax,ymax,zmin);
|
||||
edges[2].first = edges[1].second; edges[2].second.set(xmin,ymax,zmin);
|
||||
edges[3].first = edges[2].second; edges[3].second = edges[0].first;
|
||||
|
||||
edges[4].first.set(xmin,ymin,zmax); edges[4].second.set(xmax,ymin,zmax);
|
||||
edges[5].first = edges[4].second; edges[5].second.set(xmax,ymax,zmax);
|
||||
edges[6].first = edges[5].second; edges[6].second.set(xmin,ymax,zmax);
|
||||
edges[7].first = edges[6].second; edges[7].second = edges[4].first;
|
||||
|
||||
edges[ 8].first = edges[0].first; edges[ 8].second = edges[4].first;
|
||||
edges[ 9].first = edges[1].first; edges[ 9].second = edges[5].first;
|
||||
edges[10].first = edges[2].first; edges[10].second = edges[6].first;
|
||||
edges[11].first = edges[3].first; edges[11].second = edges[7].first;
|
||||
|
||||
// Clip the edges by the planes
|
||||
//
|
||||
G4int nedges = edges.size();
|
||||
G4int nplanes = pPlanes.size();
|
||||
for (G4int k=0; k<nedges; k++)
|
||||
{
|
||||
G4Point3D p1 = edges[k].first;
|
||||
G4Point3D p2 = edges[k].second;
|
||||
G4bool exist = true;
|
||||
for (G4int i=0; i<nplanes; i++) {
|
||||
// Clip current edge
|
||||
G4double d1 = pPlanes[i].distance(p1);
|
||||
G4double d2 = pPlanes[i].distance(p2);
|
||||
if (d1 > 0.0) {
|
||||
if (d2 > 0.0) { exist = false; break; } // go to next edge
|
||||
p1 = (p2*d1-p1*d2)/(d1-d2); // move p1
|
||||
} else {
|
||||
if (d2 > 0.0) { p2 = (p1*d2-p2*d1)/(d2-d1); } // move p2
|
||||
}
|
||||
}
|
||||
// Adjust the extent
|
||||
if (exist) {
|
||||
emin.setX(std::min(std::min(p1.x(),p2.x()),emin.x()));
|
||||
emin.setY(std::min(std::min(p1.y(),p2.y()),emin.y()));
|
||||
emin.setZ(std::min(std::min(p1.z(),p2.z()),emin.z()));
|
||||
|
||||
emax.setX(std::max(std::max(p1.x(),p2.x()),emax.x()));
|
||||
emax.setY(std::max(std::max(p1.y(),p2.y()),emax.y()));
|
||||
emax.setZ(std::max(std::max(p1.z(),p2.z()),emax.z()));
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the extent back
|
||||
pExtent.first = emin;
|
||||
pExtent.second = emax;
|
||||
}
|
||||
@@ -24,23 +24,24 @@
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: G4ReflectedSolid.cc 66356 2012-12-18 09:02:32Z gcosmo $
|
||||
// $Id: G4ReflectedSolid.cc 97686 2016-06-07 09:27:32Z gcosmo $
|
||||
//
|
||||
//
|
||||
// Implementation for G4ReflectedSolid class for boolean
|
||||
// operations between other solids
|
||||
// Implementation for G4ReflectedSolid class
|
||||
//
|
||||
// Author: Vladimir Grichine, 23.07.01 (Vladimir.Grichine@cern.ch)
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#include "G4ReflectedSolid.hh"
|
||||
#include "G4BoundingEnvelope.hh"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "G4Point3D.hh"
|
||||
#include "G4Normal3D.hh"
|
||||
#include "G4Vector3D.hh"
|
||||
|
||||
#include "G4AffineTransform.hh"
|
||||
#include "G4VoxelLimits.hh"
|
||||
|
||||
#include "G4VPVParameterisation.hh"
|
||||
@@ -48,27 +49,17 @@
|
||||
#include "G4VGraphicsScene.hh"
|
||||
#include "G4Polyhedron.hh"
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Constructor using HepTransform3D, in fact HepReflect3D
|
||||
|
||||
G4ReflectedSolid::G4ReflectedSolid( const G4String& pName,
|
||||
G4VSolid* pSolid ,
|
||||
const G4Transform3D& transform )
|
||||
: G4VSolid(pName), fpPolyhedron(0)
|
||||
const G4Transform3D& transform )
|
||||
: G4VSolid(pName), fRebuildPolyhedron(false), fpPolyhedron(0)
|
||||
{
|
||||
fPtrSolid = pSolid ;
|
||||
G4RotationMatrix rotMatrix ;
|
||||
|
||||
fDirectTransform =
|
||||
new G4AffineTransform(rotMatrix, transform.getTranslation()) ;
|
||||
fPtrTransform =
|
||||
new G4AffineTransform(rotMatrix, transform.getTranslation()) ;
|
||||
fPtrTransform->Invert() ;
|
||||
|
||||
fDirectTransform3D = new G4Transform3D(transform) ;
|
||||
fPtrTransform3D = new G4Transform3D(transform.inverse()) ;
|
||||
fPtrSolid = pSolid;
|
||||
fDirectTransform3D = new G4Transform3D(transform);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
@@ -76,28 +67,17 @@ G4ReflectedSolid::G4ReflectedSolid( const G4String& pName,
|
||||
|
||||
G4ReflectedSolid::~G4ReflectedSolid()
|
||||
{
|
||||
if(fPtrTransform)
|
||||
{
|
||||
delete fPtrTransform; fPtrTransform=0;
|
||||
delete fDirectTransform; fDirectTransform=0;
|
||||
}
|
||||
if(fPtrTransform3D)
|
||||
{
|
||||
delete fPtrTransform3D; fPtrTransform3D=0;
|
||||
delete fDirectTransform3D; fDirectTransform3D=0;
|
||||
}
|
||||
delete fpPolyhedron;
|
||||
delete fDirectTransform3D; fDirectTransform3D=0;
|
||||
delete fpPolyhedron; fpPolyhedron = 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
G4ReflectedSolid::G4ReflectedSolid(const G4ReflectedSolid& rhs)
|
||||
: G4VSolid(rhs), fPtrSolid(rhs.fPtrSolid), fpPolyhedron(0)
|
||||
: G4VSolid(rhs), fPtrSolid(rhs.fPtrSolid),
|
||||
fRebuildPolyhedron(false), fpPolyhedron(0)
|
||||
{
|
||||
fPtrTransform = new G4AffineTransform(*rhs.fPtrTransform);
|
||||
fDirectTransform = new G4AffineTransform(*rhs.fDirectTransform);
|
||||
fPtrTransform3D = new G4Transform3D(*rhs.fPtrTransform3D);
|
||||
fDirectTransform3D = new G4Transform3D(*rhs.fDirectTransform3D);
|
||||
}
|
||||
|
||||
@@ -116,15 +96,11 @@ G4ReflectedSolid& G4ReflectedSolid::operator=(const G4ReflectedSolid& rhs)
|
||||
|
||||
// Copy data
|
||||
//
|
||||
fPtrSolid= rhs.fPtrSolid; fpPolyhedron= 0;
|
||||
delete fPtrTransform;
|
||||
fPtrTransform= new G4AffineTransform(*rhs.fPtrTransform);
|
||||
delete fDirectTransform;
|
||||
fDirectTransform= new G4AffineTransform(*rhs.fDirectTransform);
|
||||
delete fPtrTransform3D;
|
||||
fPtrTransform3D= new G4Transform3D(*rhs.fPtrTransform3D);
|
||||
fPtrSolid= rhs.fPtrSolid;
|
||||
delete fDirectTransform3D;
|
||||
fDirectTransform3D= new G4Transform3D(*rhs.fDirectTransform3D);
|
||||
fRebuildPolyhedron = false;
|
||||
delete fpPolyhedron; fpPolyhedron= 0;
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -154,48 +130,11 @@ G4VSolid* G4ReflectedSolid::GetConstituentMovedSolid() const
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
G4AffineTransform G4ReflectedSolid::GetTransform() const
|
||||
{
|
||||
G4AffineTransform aTransform = *fPtrTransform;
|
||||
return aTransform;
|
||||
}
|
||||
|
||||
void G4ReflectedSolid::SetTransform(G4AffineTransform& transform)
|
||||
{
|
||||
fPtrTransform = &transform ;
|
||||
fpPolyhedron = 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
G4AffineTransform G4ReflectedSolid::GetDirectTransform() const
|
||||
{
|
||||
G4AffineTransform aTransform= *fDirectTransform;
|
||||
return aTransform;
|
||||
}
|
||||
|
||||
void G4ReflectedSolid::SetDirectTransform(G4AffineTransform& transform)
|
||||
{
|
||||
fDirectTransform = &transform ;
|
||||
fpPolyhedron = 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
G4Transform3D G4ReflectedSolid::GetTransform3D() const
|
||||
{
|
||||
G4Transform3D aTransform = *fPtrTransform3D;
|
||||
return aTransform;
|
||||
return fDirectTransform3D->inverse();
|
||||
}
|
||||
|
||||
void G4ReflectedSolid::SetTransform3D(G4Transform3D& transform)
|
||||
{
|
||||
fPtrTransform3D = &transform ;
|
||||
fpPolyhedron = 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
G4Transform3D G4ReflectedSolid::GetDirectTransform3D() const
|
||||
{
|
||||
G4Transform3D aTransform= *fDirectTransform3D;
|
||||
@@ -204,58 +143,8 @@ G4Transform3D G4ReflectedSolid::GetDirectTransform3D() const
|
||||
|
||||
void G4ReflectedSolid::SetDirectTransform3D(G4Transform3D& transform)
|
||||
{
|
||||
fDirectTransform3D = &transform ;
|
||||
fpPolyhedron = 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
G4RotationMatrix G4ReflectedSolid::GetFrameRotation() const
|
||||
{
|
||||
G4RotationMatrix InvRotation= fDirectTransform->NetRotation();
|
||||
return InvRotation;
|
||||
}
|
||||
|
||||
void G4ReflectedSolid::SetFrameRotation(const G4RotationMatrix& matrix)
|
||||
{
|
||||
fDirectTransform->SetNetRotation(matrix);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
G4ThreeVector G4ReflectedSolid::GetFrameTranslation() const
|
||||
{
|
||||
return fPtrTransform->NetTranslation();
|
||||
}
|
||||
|
||||
void G4ReflectedSolid::SetFrameTranslation(const G4ThreeVector& vector)
|
||||
{
|
||||
fPtrTransform->SetNetTranslation(vector);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
G4RotationMatrix G4ReflectedSolid::GetObjectRotation() const
|
||||
{
|
||||
G4RotationMatrix Rotation= fPtrTransform->NetRotation();
|
||||
return Rotation;
|
||||
}
|
||||
|
||||
void G4ReflectedSolid::SetObjectRotation(const G4RotationMatrix& matrix)
|
||||
{
|
||||
fPtrTransform->SetNetRotation(matrix);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
G4ThreeVector G4ReflectedSolid::GetObjectTranslation() const
|
||||
{
|
||||
return fDirectTransform->NetTranslation();
|
||||
}
|
||||
|
||||
void G4ReflectedSolid::SetObjectTranslation(const G4ThreeVector& vector)
|
||||
{
|
||||
fDirectTransform->SetNetTranslation(vector);
|
||||
fDirectTransform3D = &transform;
|
||||
fRebuildPolyhedron = true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
@@ -267,171 +156,36 @@ G4ReflectedSolid::CalculateExtent( const EAxis pAxis,
|
||||
const G4VoxelLimits& pVoxelLimit,
|
||||
const G4AffineTransform& pTransform,
|
||||
G4double& pMin,
|
||||
G4double& pMax ) const
|
||||
G4double& pMax ) const
|
||||
{
|
||||
|
||||
G4VoxelLimits unLimit;
|
||||
G4AffineTransform unTransform;
|
||||
|
||||
G4double x1 = -kInfinity, x2 = kInfinity,
|
||||
y1 = -kInfinity, y2 = kInfinity,
|
||||
z1 = -kInfinity, z2 = kInfinity;
|
||||
// Find bounding box
|
||||
G4double x1,x2,y1,y2,z1,z2;
|
||||
fPtrSolid->CalculateExtent(kXAxis,unLimit,unTransform,x1,x2);
|
||||
fPtrSolid->CalculateExtent(kYAxis,unLimit,unTransform,y1,y2);
|
||||
fPtrSolid->CalculateExtent(kZAxis,unLimit,unTransform,z1,z2);
|
||||
G4BoundingEnvelope bbox(G4Point3D(x1,y1,z1),
|
||||
G4Point3D(x2,y2,z2),kCarTolerance);
|
||||
|
||||
G4bool existsAfterClip = false ;
|
||||
existsAfterClip =
|
||||
fPtrSolid->CalculateExtent(kXAxis,unLimit,unTransform,x1,x2);
|
||||
existsAfterClip =
|
||||
fPtrSolid->CalculateExtent(kYAxis,unLimit,unTransform,y1,y2);
|
||||
existsAfterClip =
|
||||
fPtrSolid->CalculateExtent(kZAxis,unLimit,unTransform,z1,z2);
|
||||
// Set combined transformation
|
||||
G4Transform3D transform3D =
|
||||
G4Transform3D(pTransform.NetRotation().inverse(),
|
||||
pTransform.NetTranslation())*(*fDirectTransform3D);
|
||||
|
||||
existsAfterClip = false;
|
||||
pMin = +kInfinity ;
|
||||
pMax = -kInfinity ;
|
||||
|
||||
G4Transform3D pTransform3D = G4Transform3D(pTransform.NetRotation().inverse(),
|
||||
pTransform.NetTranslation());
|
||||
|
||||
G4Transform3D transform3D = pTransform3D*(*fDirectTransform3D);
|
||||
|
||||
G4Point3D tmpPoint;
|
||||
|
||||
// Calculate rotated vertex coordinates
|
||||
|
||||
G4ThreeVectorList* vertices = new G4ThreeVectorList();
|
||||
|
||||
if (vertices)
|
||||
{
|
||||
vertices->reserve(8);
|
||||
|
||||
G4ThreeVector vertex0(x1,y1,z1) ;
|
||||
tmpPoint = transform3D*G4Point3D(vertex0);
|
||||
vertex0 = G4ThreeVector(tmpPoint.x(),tmpPoint.y(),tmpPoint.z());
|
||||
vertices->push_back(vertex0);
|
||||
|
||||
G4ThreeVector vertex1(x2,y1,z1) ;
|
||||
tmpPoint = transform3D*G4Point3D(vertex1);
|
||||
vertex1 = G4ThreeVector(tmpPoint.x(),tmpPoint.y(),tmpPoint.z());
|
||||
vertices->push_back(vertex1);
|
||||
|
||||
G4ThreeVector vertex2(x2,y2,z1) ;
|
||||
tmpPoint = transform3D*G4Point3D(vertex2);
|
||||
vertex2 = G4ThreeVector(tmpPoint.x(),tmpPoint.y(),tmpPoint.z());
|
||||
vertices->push_back(vertex2);
|
||||
|
||||
G4ThreeVector vertex3(x1,y2,z1) ;
|
||||
tmpPoint = transform3D*G4Point3D(vertex3);
|
||||
vertex3 = G4ThreeVector(tmpPoint.x(),tmpPoint.y(),tmpPoint.z());
|
||||
vertices->push_back(vertex3);
|
||||
|
||||
G4ThreeVector vertex4(x1,y1,z2) ;
|
||||
tmpPoint = transform3D*G4Point3D(vertex4);
|
||||
vertex4 = G4ThreeVector(tmpPoint.x(),tmpPoint.y(),tmpPoint.z());
|
||||
vertices->push_back(vertex4);
|
||||
|
||||
G4ThreeVector vertex5(x2,y1,z2) ;
|
||||
tmpPoint = transform3D*G4Point3D(vertex5);
|
||||
vertex5 = G4ThreeVector(tmpPoint.x(),tmpPoint.y(),tmpPoint.z());
|
||||
vertices->push_back(vertex5);
|
||||
|
||||
G4ThreeVector vertex6(x2,y2,z2) ;
|
||||
tmpPoint = transform3D*G4Point3D(vertex6);
|
||||
vertex6 = G4ThreeVector(tmpPoint.x(),tmpPoint.y(),tmpPoint.z());
|
||||
vertices->push_back(vertex6);
|
||||
|
||||
G4ThreeVector vertex7(x1,y2,z2) ;
|
||||
tmpPoint = transform3D*G4Point3D(vertex7);
|
||||
vertex7 = G4ThreeVector(tmpPoint.x(),tmpPoint.y(),tmpPoint.z());
|
||||
vertices->push_back(vertex7);
|
||||
}
|
||||
else
|
||||
{
|
||||
DumpInfo();
|
||||
G4Exception("G4ReflectedSolid::CalculateExtent()",
|
||||
"GeomMgt0003", FatalException,
|
||||
"Error in allocation of vertices. Out of memory !");
|
||||
}
|
||||
|
||||
ClipCrossSection(vertices,0,pVoxelLimit,pAxis,pMin,pMax) ;
|
||||
ClipCrossSection(vertices,4,pVoxelLimit,pAxis,pMin,pMax) ;
|
||||
ClipBetweenSections(vertices,0,pVoxelLimit,pAxis,pMin,pMax) ;
|
||||
|
||||
if (pVoxelLimit.IsLimited(pAxis) == false)
|
||||
{
|
||||
if ( pMin != kInfinity || pMax != -kInfinity )
|
||||
{
|
||||
existsAfterClip = true ;
|
||||
|
||||
// Add 2*tolerance to avoid precision troubles
|
||||
|
||||
pMin -= kCarTolerance;
|
||||
pMax += kCarTolerance;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
G4ThreeVector clipCentre(
|
||||
( pVoxelLimit.GetMinXExtent()+pVoxelLimit.GetMaxXExtent())*0.5,
|
||||
( pVoxelLimit.GetMinYExtent()+pVoxelLimit.GetMaxYExtent())*0.5,
|
||||
( pVoxelLimit.GetMinZExtent()+pVoxelLimit.GetMaxZExtent())*0.5);
|
||||
|
||||
if ( pMin != kInfinity || pMax != -kInfinity )
|
||||
{
|
||||
existsAfterClip = true ;
|
||||
|
||||
|
||||
// Check to see if endpoints are in the solid
|
||||
|
||||
clipCentre(pAxis) = pVoxelLimit.GetMinExtent(pAxis);
|
||||
|
||||
if (Inside(transform3D.inverse()*G4Point3D(clipCentre)) != kOutside)
|
||||
{
|
||||
pMin = pVoxelLimit.GetMinExtent(pAxis);
|
||||
}
|
||||
else
|
||||
{
|
||||
pMin -= kCarTolerance;
|
||||
}
|
||||
clipCentre(pAxis) = pVoxelLimit.GetMaxExtent(pAxis);
|
||||
|
||||
if (Inside(transform3D.inverse()*G4Point3D(clipCentre)) != kOutside)
|
||||
{
|
||||
pMax = pVoxelLimit.GetMaxExtent(pAxis);
|
||||
}
|
||||
else
|
||||
{
|
||||
pMax += kCarTolerance;
|
||||
}
|
||||
}
|
||||
// Check for case where completely enveloping clipping volume
|
||||
// If point inside then we are confident that the solid completely
|
||||
// envelopes the clipping volume. Hence set min/max extents according
|
||||
// to clipping volume extents along the specified axis.
|
||||
|
||||
else if (Inside(transform3D.inverse()*G4Point3D(clipCentre)) != kOutside)
|
||||
{
|
||||
existsAfterClip = true ;
|
||||
pMin = pVoxelLimit.GetMinExtent(pAxis) ;
|
||||
pMax = pVoxelLimit.GetMaxExtent(pAxis) ;
|
||||
}
|
||||
}
|
||||
delete vertices;
|
||||
return existsAfterClip;
|
||||
// Find extent
|
||||
return bbox.CalculateExtent(pAxis,pVoxelLimit,transform3D,pMin,pMax);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
|
||||
EInside G4ReflectedSolid::Inside(const G4ThreeVector& p) const
|
||||
EInside G4ReflectedSolid::Inside(const G4ThreeVector& p ) const
|
||||
{
|
||||
|
||||
G4Point3D newPoint = (*fDirectTransform3D)*G4Point3D(p) ;
|
||||
// G4Point3D newPoint = (*fPtrTransform3D)*G4Point3D(p) ;
|
||||
|
||||
return fPtrSolid->Inside(G4ThreeVector(newPoint.x(),
|
||||
newPoint.y(),
|
||||
newPoint.z())) ;
|
||||
G4ThreeVector newPoint = (*fDirectTransform3D)*G4Point3D(p);
|
||||
return fPtrSolid->Inside(newPoint);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
@@ -441,15 +195,9 @@ EInside G4ReflectedSolid::Inside(const G4ThreeVector& p) const
|
||||
G4ThreeVector
|
||||
G4ReflectedSolid::SurfaceNormal( const G4ThreeVector& p ) const
|
||||
{
|
||||
G4Point3D newPoint = (*fDirectTransform3D)*G4Point3D(p) ;
|
||||
G4ThreeVector normal =
|
||||
fPtrSolid->SurfaceNormal(G4ThreeVector(newPoint.x(),
|
||||
newPoint.y(),
|
||||
newPoint.z() ) ) ;
|
||||
G4Point3D newN = (*fDirectTransform3D)*G4Point3D(normal) ;
|
||||
newN.unit() ;
|
||||
|
||||
return G4ThreeVector(newN.x(),newN.y(),newN.z()) ;
|
||||
G4ThreeVector newPoint = (*fDirectTransform3D)*G4Point3D(p);
|
||||
G4Vector3D normal = fPtrSolid->SurfaceNormal(newPoint);
|
||||
return (*fDirectTransform3D)*normal;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
@@ -458,14 +206,11 @@ G4ReflectedSolid::SurfaceNormal( const G4ThreeVector& p ) const
|
||||
|
||||
G4double
|
||||
G4ReflectedSolid::DistanceToIn( const G4ThreeVector& p,
|
||||
const G4ThreeVector& v ) const
|
||||
const G4ThreeVector& v ) const
|
||||
{
|
||||
G4Point3D newPoint = (*fDirectTransform3D)*G4Point3D(p) ;
|
||||
G4Point3D newDirection = (*fDirectTransform3D)*G4Point3D(v) ;
|
||||
newDirection.unit() ;
|
||||
return fPtrSolid->DistanceToIn(
|
||||
G4ThreeVector(newPoint.x(),newPoint.y(),newPoint.z()),
|
||||
G4ThreeVector(newDirection.x(),newDirection.y(),newDirection.z())) ;
|
||||
G4ThreeVector newPoint = (*fDirectTransform3D)*G4Point3D(p);
|
||||
G4ThreeVector newDirection = (*fDirectTransform3D)*G4Vector3D(v);
|
||||
return fPtrSolid->DistanceToIn(newPoint,newDirection);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
@@ -474,11 +219,10 @@ G4ReflectedSolid::DistanceToIn( const G4ThreeVector& p,
|
||||
// two solids
|
||||
|
||||
G4double
|
||||
G4ReflectedSolid::DistanceToIn( const G4ThreeVector& p) const
|
||||
G4ReflectedSolid::DistanceToIn( const G4ThreeVector& p ) const
|
||||
{
|
||||
G4Point3D newPoint = (*fDirectTransform3D)*G4Point3D(p) ;
|
||||
return fPtrSolid->DistanceToIn(
|
||||
G4ThreeVector(newPoint.x(),newPoint.y(),newPoint.z())) ;
|
||||
G4ThreeVector newPoint = (*fDirectTransform3D)*G4Point3D(p);
|
||||
return fPtrSolid->DistanceToIn(newPoint);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
@@ -490,26 +234,20 @@ G4ReflectedSolid::DistanceToOut( const G4ThreeVector& p,
|
||||
const G4ThreeVector& v,
|
||||
const G4bool calcNorm,
|
||||
G4bool *validNorm,
|
||||
G4ThreeVector *n ) const
|
||||
G4ThreeVector *n ) const
|
||||
{
|
||||
G4ThreeVector solNorm ;
|
||||
G4ThreeVector solNorm;
|
||||
|
||||
G4Point3D newPoint = (*fDirectTransform3D)*G4Point3D(p) ;
|
||||
G4Point3D newDirection = (*fDirectTransform3D)*G4Point3D(v);
|
||||
newDirection.unit() ;
|
||||
G4ThreeVector newPoint = (*fDirectTransform3D)*G4Point3D(p);
|
||||
G4ThreeVector newDirection = (*fDirectTransform3D)*G4Vector3D(v);
|
||||
|
||||
G4double dist =
|
||||
fPtrSolid->DistanceToOut(
|
||||
G4ThreeVector(newPoint.x(),newPoint.y(),newPoint.z()),
|
||||
G4ThreeVector(newDirection.x(),newDirection.y(),newDirection.z()),
|
||||
calcNorm, validNorm, &solNorm) ;
|
||||
G4double dist = fPtrSolid->DistanceToOut(newPoint, newDirection,
|
||||
calcNorm, validNorm, &solNorm);
|
||||
if(calcNorm)
|
||||
{
|
||||
G4Point3D newN = (*fDirectTransform3D)*G4Point3D(solNorm);
|
||||
newN.unit() ;
|
||||
*n = G4ThreeVector(newN.x(),newN.y(),newN.z());
|
||||
*n = (*fDirectTransform3D)*G4Vector3D(solNorm);
|
||||
}
|
||||
return dist ;
|
||||
return dist;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
@@ -519,9 +257,8 @@ G4ReflectedSolid::DistanceToOut( const G4ThreeVector& p,
|
||||
G4double
|
||||
G4ReflectedSolid::DistanceToOut( const G4ThreeVector& p ) const
|
||||
{
|
||||
G4Point3D newPoint = (*fDirectTransform3D)*G4Point3D(p);
|
||||
return fPtrSolid->DistanceToOut(
|
||||
G4ThreeVector(newPoint.x(),newPoint.y(),newPoint.z()));
|
||||
G4ThreeVector newPoint = (*fDirectTransform3D)*G4Point3D(p);
|
||||
return fPtrSolid->DistanceToOut(newPoint);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
@@ -546,10 +283,8 @@ G4ReflectedSolid::ComputeDimensions( G4VPVParameterisation*,
|
||||
|
||||
G4ThreeVector G4ReflectedSolid::GetPointOnSurface() const
|
||||
{
|
||||
G4ThreeVector p = fPtrSolid->GetPointOnSurface();
|
||||
G4Point3D newPoint = (*fDirectTransform3D)*G4Point3D(p);
|
||||
|
||||
return G4ThreeVector(newPoint.x(),newPoint.y(),newPoint.z());
|
||||
G4ThreeVector p = fPtrSolid->GetPointOnSurface();
|
||||
return (*fDirectTransform3D)*G4Point3D(p);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -578,10 +313,10 @@ std::ostream& G4ReflectedSolid::StreamInfo(std::ostream& os) const
|
||||
os << "===========================================================\n"
|
||||
<< " Transformations: \n"
|
||||
<< " Direct transformation - translation : \n"
|
||||
<< " " << fDirectTransform->NetTranslation() << "\n"
|
||||
<< " " << fDirectTransform3D->getTranslation() << "\n"
|
||||
<< " - rotation : \n"
|
||||
<< " ";
|
||||
fDirectTransform->NetRotation().print(os);
|
||||
fDirectTransform3D->getRotation().print(os);
|
||||
os << "\n"
|
||||
<< "===========================================================\n";
|
||||
|
||||
@@ -631,11 +366,12 @@ G4Polyhedron*
|
||||
G4ReflectedSolid::GetPolyhedron () const
|
||||
{
|
||||
if (!fpPolyhedron ||
|
||||
fRebuildPolyhedron ||
|
||||
fpPolyhedron->GetNumberOfRotationStepsAtTimeOfCreation() !=
|
||||
fpPolyhedron->GetNumberOfRotationSteps())
|
||||
{
|
||||
delete fpPolyhedron;
|
||||
fpPolyhedron = CreatePolyhedron ();
|
||||
fpPolyhedron = CreatePolyhedron();
|
||||
fRebuildPolyhedron = false;
|
||||
}
|
||||
return fpPolyhedron;
|
||||
}
|
||||
|
||||
@@ -34,15 +34,15 @@
|
||||
|
||||
#include "G4USolid.hh"
|
||||
|
||||
#if defined(G4GEOM_USE_USOLIDS)
|
||||
#if ( defined(G4GEOM_USE_USOLIDS) || defined(G4GEOM_USE_PARTIAL_USOLIDS) )
|
||||
|
||||
#include "G4AffineTransform.hh"
|
||||
#include "G4VoxelLimits.hh"
|
||||
#include "G4VGraphicsScene.hh"
|
||||
#include "G4Polyhedron.hh"
|
||||
#include "G4PolyhedronArbitrary.hh"
|
||||
#include "G4VisExtent.hh"
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4GeometryTolerance.hh"
|
||||
|
||||
#include "G4AutoLock.hh"
|
||||
|
||||
@@ -82,13 +82,8 @@ EInside G4USolid::Inside(const G4ThreeVector& p) const
|
||||
|
||||
in_temp = fShape->Inside(pt);
|
||||
|
||||
#ifndef G4USE_STD11
|
||||
if (in_temp == VUSolid::eSurface)return kSurface;
|
||||
if (in_temp == VUSolid::eInside)return kInside;
|
||||
#else
|
||||
if (in_temp == VUSolid::EnumInside::eSurface)return kSurface;
|
||||
if (in_temp == VUSolid::EnumInside::eInside)return kInside;
|
||||
#endif
|
||||
if (in_temp == VUSolid::EnumInside::eSurface) return kSurface;
|
||||
if (in_temp == VUSolid::EnumInside::eInside) return kInside;
|
||||
|
||||
return in;
|
||||
}
|
||||
@@ -105,7 +100,7 @@ G4ThreeVector G4USolid::SurfaceNormal(const G4ThreeVector& pt) const
|
||||
}
|
||||
|
||||
G4double G4USolid::DistanceToIn(const G4ThreeVector& pt,
|
||||
const G4ThreeVector& d)const
|
||||
const G4ThreeVector& d) const
|
||||
{
|
||||
UVector3 p;
|
||||
p.x() = pt.x();
|
||||
@@ -116,7 +111,8 @@ G4double G4USolid::DistanceToIn(const G4ThreeVector& pt,
|
||||
v.y() = d.y();
|
||||
v.z() = d.z(); // better assign at construction
|
||||
G4double dist = fShape->DistanceToIn(p, v);
|
||||
if (dist > kInfinity) dist = kInfinity;
|
||||
if (dist > kInfinity) return kInfinity;
|
||||
// return (dist > halfTolerance) ? dist : 0.0;
|
||||
return dist;
|
||||
}
|
||||
|
||||
@@ -127,7 +123,8 @@ G4double G4USolid::DistanceToIn(const G4ThreeVector& pt) const
|
||||
p.y() = pt.y();
|
||||
p.z() = pt.z(); // better assign at construction
|
||||
G4double dist = fShape->SafetyFromOutside(p); // true?
|
||||
if (dist > kInfinity) dist = kInfinity;
|
||||
if (dist > kInfinity) return kInfinity;
|
||||
// return (dist > halfTolerance) ? dist : 0.0;
|
||||
return dist;
|
||||
}
|
||||
|
||||
@@ -146,19 +143,21 @@ G4double G4USolid::DistanceToOut(const G4ThreeVector& pt,
|
||||
v.y() = d.y();
|
||||
v.z() = d.z(); // better assign at construction
|
||||
UVector3 n;
|
||||
bool valid;
|
||||
G4double dist = fShape->DistanceToOut(p, v, n,valid); // should use local variable
|
||||
G4bool valid;
|
||||
G4double dist = fShape->DistanceToOut(p, v, n, valid); // should use local variable
|
||||
if(calcNorm)
|
||||
{
|
||||
if(valid){ *validNorm = true;}
|
||||
else {* validNorm =false;}
|
||||
if(*validNorm)
|
||||
{ norm->setX(n.x());
|
||||
if(valid){ *validNorm = true; }
|
||||
else { *validNorm = false; }
|
||||
if(*validNorm) // *norm = n, but only after calcNorm check
|
||||
{
|
||||
norm->setX(n.x());
|
||||
norm->setY(n.y());
|
||||
norm->setZ(n.z());
|
||||
} // *norm = n, but only after calcNorm check
|
||||
}
|
||||
}
|
||||
if (dist > kInfinity) dist = kInfinity;
|
||||
if (dist > kInfinity) return kInfinity;
|
||||
// return (dist > halfTolerance) ? dist : 0.0;
|
||||
return dist;
|
||||
}
|
||||
|
||||
@@ -168,7 +167,9 @@ G4double G4USolid::DistanceToOut(const G4ThreeVector& pt) const
|
||||
p.x() = pt.x();
|
||||
p.y() = pt.y();
|
||||
p.z() = pt.z(); // better assign at construction
|
||||
return fShape->SafetyFromInside(p); // true?
|
||||
G4double dist = fShape->SafetyFromInside(p); // true?
|
||||
// return (dist > halfTolerance) ? dist : 0.0;
|
||||
return dist;
|
||||
}
|
||||
|
||||
G4double G4USolid::GetCubicVolume()
|
||||
@@ -452,108 +453,13 @@ G4USolid::CreateRotatedVertices(const G4AffineTransform& pTransform) const
|
||||
|
||||
G4Polyhedron* G4USolid::CreatePolyhedron() const
|
||||
{
|
||||
G4int index = 0;
|
||||
if (fShape->GetEntityType() == "Box")
|
||||
{
|
||||
double array[3];
|
||||
fShape->GetParametersList(index, array);
|
||||
return new G4PolyhedronBox(array[0], array[1], array[2]);
|
||||
}
|
||||
if (fShape->GetEntityType() == "Tubs")
|
||||
{
|
||||
double array[5];
|
||||
fShape->GetParametersList(index, array);
|
||||
return new G4PolyhedronTubs(array[0], array[1], array[2], array[3], array[4]);
|
||||
}
|
||||
if (fShape->GetEntityType() == "Cons")
|
||||
{
|
||||
double array[7];
|
||||
fShape->GetParametersList(index, array);
|
||||
return new G4PolyhedronCons(array[0], array[1], array[2], array[3], array[4], array[5], array[6]);
|
||||
}
|
||||
if (fShape->GetEntityType() == "Orb")
|
||||
{
|
||||
double array[1];
|
||||
fShape->GetParametersList(index, array);
|
||||
return new G4PolyhedronSphere(0., array[0], 0., 2 * pi, 0., pi);
|
||||
}
|
||||
if (fShape->GetEntityType() == "Sphere")
|
||||
{
|
||||
double array[6];
|
||||
fShape->GetParametersList(index, array);
|
||||
return new G4PolyhedronSphere(array[0], array[1], array[2], array[3], array[4], array[5]);
|
||||
}
|
||||
if (fShape->GetEntityType() == "Tet")
|
||||
{
|
||||
double array[12];
|
||||
fShape->GetParametersList(index, array);
|
||||
G4Polyhedron* ph = new G4Polyhedron;
|
||||
double xyz[4][3];
|
||||
static int faces[4][4] = {{1, 3, 2, 0}, {1, 4, 3, 0}, {1, 2, 4, 0}, {2, 3, 4, 0}};
|
||||
xyz[0][0] = array[0];
|
||||
xyz[0][1] = array[1];
|
||||
xyz[0][2] = array[2];
|
||||
xyz[1][0] = array[3];
|
||||
xyz[1][1] = array[4];
|
||||
xyz[1][2] = array[5];
|
||||
xyz[2][0] = array[6];
|
||||
xyz[2][1] = array[7];
|
||||
xyz[2][2] = array[8];
|
||||
xyz[3][0] = array[9];
|
||||
xyz[3][1] = array[10];
|
||||
xyz[3][2] = array[11];
|
||||
|
||||
ph->createPolyhedron(4, 4, xyz, faces);
|
||||
return ph;
|
||||
}
|
||||
if (fShape->GetEntityType() == "Trd")
|
||||
{
|
||||
double array[5];
|
||||
fShape->GetParametersList(index, array);
|
||||
return new G4PolyhedronTrd2(array[0], array[1], array[2], array[3], array[4]);
|
||||
}
|
||||
if (fShape->GetEntityType() == "Trap")
|
||||
{
|
||||
double array[12];
|
||||
fShape->GetParametersList(index, array);
|
||||
double phi = (array[11] != 1.0) ? (std::atan(array[10] / array[9])) : (0.0);
|
||||
double alpha1 = std::atan(array[4]);
|
||||
double alpha2 = std::atan(array[8]);
|
||||
double theta = std::acos(array[11]);
|
||||
|
||||
return new G4PolyhedronTrap(array[0], theta, phi,
|
||||
array[1], array[2], array[3], alpha1,
|
||||
array[5], array[6], array[7], alpha2);
|
||||
}
|
||||
|
||||
/*
|
||||
if(fShape->GetEntityType()=="TessellatedSolid"){
|
||||
|
||||
G4Polyhedron *uPolyhedron=fShape->GetPolyhedron();
|
||||
std::size_t nVertices = (*uPolyhedron).vertices.size();
|
||||
std::size_t nFacets = (*uPolyhedron).facets.size();
|
||||
|
||||
G4PolyhedronArbitrary *polyhedron =
|
||||
new G4PolyhedronArbitrary (nVertices, nFacets);
|
||||
|
||||
for (std::vector<UVector3>::const_iterator v = (*uPolyhedron).vertices.begin();
|
||||
v!=(*uPolyhedron).vertices.end(); v++)
|
||||
{
|
||||
UVector3 p=(*v);
|
||||
G4ThreeVector pt(p.x(),p.y(),p.z());
|
||||
|
||||
polyhedron->AddVertex(pt);
|
||||
}
|
||||
for (std::vector<UFacet>::const_iterator f=(*uPolyhedron).facets.begin();
|
||||
f != (*uPolyhedron).facets.end(); f++)
|
||||
{
|
||||
polyhedron->AddFacet((*f).f1,(*f).f2,(*f).f3,(*f).f4);
|
||||
}
|
||||
|
||||
return (G4Polyhedron*) polyhedron;
|
||||
}
|
||||
*/
|
||||
// Must be implemented in concrete wrappers...
|
||||
|
||||
std::ostringstream message;
|
||||
message << "Visualization not supported for USolid shape "
|
||||
<< GetEntityType() << "... Sorry!" << G4endl;
|
||||
G4Exception("G4USolid::CreatePolyhedron()", "GeomSolids0003",
|
||||
FatalException, message);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user