Import Geant4 10.0.0 source tree
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
#------------------------------------------------------------------------------
|
||||
# CMakeLists.txt
|
||||
# Module : G4geomUsolids
|
||||
# Package: Geant4.src.G4geometry.G4geomUSolids
|
||||
#
|
||||
# CMakeLists.txt for building a single granular library.
|
||||
#
|
||||
# Generated on : 24/9/2010
|
||||
#
|
||||
# $Id: CMakeLists.txt 66356 2012-12-18 09:02:32Z gcosmo $
|
||||
#
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
if(GEANT4_BUILD_GRANULAR_LIBS)
|
||||
include(Geant4MacroLibraryTargets)
|
||||
GEANT4_GRANULAR_LIBRARY_TARGET(COMPONENT sources.cmake)
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# $Id: GNUmakefile 66356 2012-12-18 09:02:32Z gcosmo $
|
||||
# --------------------------------------------------------------------
|
||||
# GNUmakefile for geometry/usolids library. Gabriele Cosmo, 16/11/96.
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
name := G4geomUSolids
|
||||
|
||||
ifndef G4INSTALL
|
||||
G4INSTALL = ../../../..
|
||||
endif
|
||||
|
||||
include $(G4INSTALL)/config/architecture.gmk
|
||||
|
||||
CPPFLAGS += -DG4GEOM_ALLOC_EXPORT
|
||||
CPPFLAGS += -I$(G4BASE)/intercoms/include \
|
||||
-I$(G4BASE)/graphics_reps/include \
|
||||
-I$(G4BASE)/global/management/include \
|
||||
-I$(G4BASE)/global/HEPGeometry/include \
|
||||
-I$(G4BASE)/geometry/management/include \
|
||||
|
||||
ifdef G4USOLDEBUG
|
||||
CPPFLAGS += -DG4USOLDEBUG
|
||||
endif
|
||||
|
||||
include $(G4INSTALL)/config/common.gmk
|
||||
@@ -0,0 +1,67 @@
|
||||
$Id: History 74238 2013-10-02 08:51:17Z gcosmo $
|
||||
-------------------------------------------------------------------
|
||||
|
||||
=========================================================
|
||||
Geant4 - an Object-Oriented Toolkit for Simulation in HEP
|
||||
=========================================================
|
||||
|
||||
Sub-Category History file
|
||||
-------------------------
|
||||
This file should be used by G4 developers and category coordinators
|
||||
to briefly summarize all major modifications introduced in the code
|
||||
and keep track of all directory-tags.
|
||||
It DOES NOT substitute the CVS log-message one should put at every
|
||||
committal in the CVS repository !
|
||||
|
||||
----------------------------------------------------------
|
||||
* Reverse chronological order (last date on top), please *
|
||||
----------------------------------------------------------
|
||||
|
||||
November 29, 2013 G.Cosmo geom-usolids-V09-06-11
|
||||
- Corrected library name in GNUmakefile and fixed comment in sources.cmake.
|
||||
|
||||
November 21, 2013 G.Cosmo geom-usolids-V09-06-10
|
||||
- Fixed compilation warning for type conversion in UVCSGfaceted
|
||||
constructor.
|
||||
|
||||
November 20, 2013 T.Mikitina geom-usolids-V09-06-09
|
||||
- Fixed Coverity defects.
|
||||
|
||||
November 14, 2013 T.Mikitina geom-usolids-V09-06-08
|
||||
- Corrected visualization methods in bridge G4USolid.
|
||||
- Corrected returned type string from USolids and added Reset()
|
||||
method to UPolycone.
|
||||
|
||||
November 13, 2013 G.Cosmo geom-usolids-V09-06-07
|
||||
- Removed useless dependency on UMultiUnion in UPolycone.
|
||||
|
||||
November 13, 2013 G.Cosmo geom-usolids-V09-06-06
|
||||
- Leave out UMultiUnion, as not yet ready for release.
|
||||
|
||||
November 12, 2013 T.Nikitina geom-usolids-V09-06-05
|
||||
- Corrected passing of parameters for normal in G4USolid::DistanceToOut(p,v).
|
||||
|
||||
November 7, 2013 G.Cosmo geom-usolids-V09-06-04
|
||||
- Moved wrappers to associated modules.
|
||||
- Added missing accessor method to UTrd.
|
||||
|
||||
November 5, 2013 G.Cosmo geom-usolids-V09-06-03
|
||||
- Code cleanup and added banners to USolids files.
|
||||
|
||||
November 1, 2013 G.Cosmo geom-usolids-V09-06-02
|
||||
- Fixed compilation error and warnings on SLC6.
|
||||
|
||||
November 1, 2013 G.Cosmo geom-usolids-V09-06-01
|
||||
- Added wrappers for Ubox, Ucons, UGenericPolycone, UMultiUnion, UOrb,
|
||||
UPolycone, UPolyhedra, USphere, UTet, UTrd, UTubs.
|
||||
Removed all other shapes not covered by the wrappers (will be included
|
||||
in a later stage).
|
||||
- Updated CMake script accordingly.
|
||||
|
||||
October 29, 2013 G.Cosmo geom-usolids-V09-06-00
|
||||
- Imported classes from the AIDA Unified Solids Library
|
||||
(see https://aidasoft.web.cern.ch/USolids).
|
||||
Shapes provided: Ubox, Ucons, UGenericPolycone, UMultiUnion, UOrb,
|
||||
UPolycone, UPolyhedra, USphere, UTet, UTrd, UTubs (including also
|
||||
shapes not foreseen to be wrapped as first stage).
|
||||
- Includes bridge class G4USolid and first wrapper class G4UBox.
|
||||
@@ -0,0 +1,183 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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:$
|
||||
// GEANT4 tag $Name:$
|
||||
//
|
||||
//
|
||||
// class G4USolid
|
||||
//
|
||||
// Class description:
|
||||
//
|
||||
// Bridge base class for solids defined in the Unified Solids Library.
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
#ifndef G4USolid_HH
|
||||
#define G4USolid_HH
|
||||
|
||||
#include "G4VSolid.hh"
|
||||
#include "VUSolid.hh"
|
||||
|
||||
class G4USolid : public G4VSolid
|
||||
{
|
||||
public: // with description
|
||||
|
||||
G4USolid(const G4String& pName, VUSolid* shape);
|
||||
// Creates a new shape, with the supplied name. No provision is made
|
||||
// for sharing a common name amongst multiple classes.
|
||||
virtual ~G4USolid();
|
||||
// Default destructor.
|
||||
|
||||
G4bool operator==(const G4USolid& s) const;
|
||||
// Return true only if addresses are the same.
|
||||
|
||||
virtual G4bool CalculateExtent(const EAxis pAxis,
|
||||
const G4VoxelLimits& pVoxelLimit,
|
||||
const G4AffineTransform& pTransform,
|
||||
G4double& pMin, G4double& pMax) const;
|
||||
// Calculate the minimum and maximum extent of the solid, when under the
|
||||
// specified transform, and within the specified limits. If the solid
|
||||
// is not intersected by the region, return false, else return true.
|
||||
|
||||
virtual EInside Inside(const G4ThreeVector& p) const;
|
||||
// Returns kOutside if the point at offset p is outside the shapes
|
||||
// boundaries plus Tolerance/2, kSurface if the point is <= Tolerance/2
|
||||
// from a surface, otherwise kInside.
|
||||
|
||||
virtual G4ThreeVector SurfaceNormal(const G4ThreeVector& p) const;
|
||||
// Returns the outwards pointing unit normal of the shape for the
|
||||
// surface closest to the point at offset p.
|
||||
|
||||
virtual G4double DistanceToIn(const G4ThreeVector& p,
|
||||
const G4ThreeVector& v) const;
|
||||
// Return the distance along the normalised vector v to the shape,
|
||||
// from the point at offset p. If there is no intersection, return
|
||||
// kInfinity. The first intersection resulting from `leaving' a
|
||||
// surface/volume is discarded. Hence, it is tolerant of points on
|
||||
// the surface of the shape.
|
||||
|
||||
virtual G4double DistanceToIn(const G4ThreeVector& p) const;
|
||||
// Calculate the distance to the nearest surface of a shape from an
|
||||
// outside point. The distance can be an underestimate.
|
||||
|
||||
virtual G4double DistanceToOut(const G4ThreeVector& p,
|
||||
const G4ThreeVector& v,
|
||||
const G4bool calcNorm = false,
|
||||
G4bool* validNorm = 0,
|
||||
G4ThreeVector* n = 0) const;
|
||||
// Return the distance along the normalised vector v to the shape,
|
||||
// from a point at an offset p inside or on the surface of the shape.
|
||||
// Intersections with surfaces, when the point is < Tolerance/2 from a
|
||||
// surface must be ignored.
|
||||
// If calcNorm==true:
|
||||
// validNorm set true if the solid lies entirely behind or on the
|
||||
// exiting surface.
|
||||
// n set to exiting outwards normal vector (undefined Magnitude).
|
||||
// validNorm set to false if the solid does not lie entirely behind
|
||||
// or on the exiting surface
|
||||
// If calcNorm==false:
|
||||
// validNorm and n are unused.
|
||||
//
|
||||
// Must be called as solid.DistanceToOut(p,v) or by specifying all
|
||||
// the parameters.
|
||||
|
||||
virtual G4double DistanceToOut(const G4ThreeVector& p) const;
|
||||
// Calculate the distance to the nearest surface of a shape from an
|
||||
// inside point. The distance can be an underestimate.
|
||||
|
||||
|
||||
virtual G4double GetCubicVolume();
|
||||
// Returns an estimation of the solid volume in internal units.
|
||||
// This method may be overloaded by derived classes to compute the
|
||||
// exact geometrical quantity for solids where this is possible,
|
||||
// or anyway to cache the computed value.
|
||||
// Note: the computed value is NOT cached.
|
||||
|
||||
virtual G4double GetSurfaceArea();
|
||||
// Return an estimation of the solid surface area in internal units.
|
||||
// This method may be overloaded by derived classes to compute the
|
||||
// exact geometrical quantity for solids where this is possible,
|
||||
// or anyway to cache the computed value.
|
||||
// Note: the computed value is NOT cached.
|
||||
|
||||
virtual G4GeometryType GetEntityType() const;
|
||||
// Provide identification of the class of an object.
|
||||
// (required for persistency and STEP interface)
|
||||
|
||||
virtual G4ThreeVector GetPointOnSurface() const;
|
||||
// Returns a random point located on the surface of the solid.
|
||||
|
||||
virtual G4VSolid* Clone() const;
|
||||
// Returns a pointer of a dynamically allocated copy of the solid.
|
||||
// Returns NULL pointer with warning in case the concrete solid does not
|
||||
// implement this method. The caller has responsibility for ownership.
|
||||
|
||||
virtual std::ostream& StreamInfo(std::ostream& os) const;
|
||||
// Dumps contents of the solid to a stream.
|
||||
|
||||
virtual void DescribeYourselfTo(G4VGraphicsScene& scene) const;
|
||||
// A "double dispatch" function which identifies the solid
|
||||
// to the graphics scene for visualization.
|
||||
|
||||
virtual G4VisExtent GetExtent() const;
|
||||
// Provide extent (bounding box) as possible hint to the graphics view.
|
||||
G4Polyhedron* CreatePolyhedron() const;
|
||||
// Create Polyhedron used for Visualisation
|
||||
virtual G4Polyhedron* GetPolyhedron() const;
|
||||
// Smart access function - creates on request and stores for future
|
||||
// access. A null pointer means "not available".
|
||||
virtual void ResetPolyhedron() const;
|
||||
//Reset Polyhedron used by Parametrisation
|
||||
public: // without description
|
||||
|
||||
G4USolid(__void__&);
|
||||
// Fake default constructor for usage restricted to direct object
|
||||
// persistency for clients requiring preallocation of memory for
|
||||
// persistifiable objects.
|
||||
|
||||
G4USolid(const G4USolid& rhs);
|
||||
G4USolid& operator=(const G4USolid& rhs);
|
||||
// Copy constructor and assignment operator.
|
||||
|
||||
VUSolid* GetSolid() const
|
||||
{
|
||||
return fShape;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
G4ThreeVectorList* CreateRotatedVertices(const G4AffineTransform& pT) const;
|
||||
|
||||
protected: // data
|
||||
|
||||
VUSolid* fShape;
|
||||
|
||||
private:
|
||||
|
||||
mutable G4Polyhedron* fPolyhedron;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,222 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UBits
|
||||
//
|
||||
// Class description:
|
||||
//
|
||||
// Container of bits
|
||||
//
|
||||
// This class provides a simple container of bits.
|
||||
// Each bit can be set and tested via the functions SetBitNumber and
|
||||
// TestBitNumber.
|
||||
// The default value of all bits is false.
|
||||
// The size of the container is automatically extended when a bit
|
||||
// number is either set or tested. To reduce the memory size of the
|
||||
// container use the Compact function, this will discard the memory
|
||||
// occupied by the upper bits that are 0.
|
||||
//
|
||||
// Created for UTessellatedSolid
|
||||
//
|
||||
// 19.10.12 Marek Gayer
|
||||
// Created from original implementation in ROOT (TBits)
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#ifndef UBits_HH
|
||||
#define UBits_HH
|
||||
|
||||
#include <cstring>
|
||||
#include <ostream>
|
||||
|
||||
class UBits
|
||||
{
|
||||
|
||||
public:
|
||||
unsigned char* fAllBits; //[fNBytes] array of UChars
|
||||
|
||||
protected:
|
||||
|
||||
unsigned int fNBits; // Highest bit set + 1
|
||||
unsigned int fNBytes; // Number of UChars in fAllBits
|
||||
|
||||
void ReserveBytes(unsigned int nbytes);
|
||||
|
||||
/*
|
||||
void DoAndEqual(const UBits& rhs);
|
||||
void DoOrEqual (const UBits& rhs);
|
||||
void DoXorEqual(const UBits& rhs);
|
||||
void DoLeftShift(unsigned int shift);
|
||||
void DoRightShift(unsigned int shift);
|
||||
void DoFlip();
|
||||
*/
|
||||
|
||||
public:
|
||||
UBits(unsigned int nbits = 0);
|
||||
UBits(const UBits&);
|
||||
UBits& operator=(const UBits& rhs);
|
||||
virtual ~UBits();
|
||||
|
||||
//----- bit manipulation
|
||||
//----- (note the difference with TObject's bit manipulations)
|
||||
void ResetAllBits(bool value = false); // if value=1 set all bits to 1
|
||||
void ResetBitNumber(unsigned int bitnumber);
|
||||
void SetBitNumber(unsigned int bitnumber, bool value = true);
|
||||
bool TestBitNumber(unsigned int bitnumber) const;
|
||||
|
||||
//----- Accessors and operator
|
||||
bool operator[](unsigned int bitnumber) const;
|
||||
|
||||
/*
|
||||
UBits& operator&=(const UBits& rhs) { DoAndEqual(rhs); return *this; }
|
||||
UBits& operator|=(const UBits& rhs) { DoOrEqual(rhs); return *this; }
|
||||
UBits& operator^=(const UBits& rhs) { DoXorEqual(rhs); return *this; }
|
||||
UBits& operator<<=(unsigned int rhs) { DoLeftShift(rhs); return *this; }
|
||||
UBits& operator>>=(unsigned int rhs) { DoRightShift(rhs); return *this; }
|
||||
UBits operator<<(unsigned int rhs) { return UBits(*this)<<= rhs; }
|
||||
UBits operator>>(unsigned int rhs) { return UBits(*this)>>= rhs; }
|
||||
UBits operator~() { UBits res(*this); res.DoFlip(); return res; }
|
||||
*/
|
||||
|
||||
//----- Optimized setters
|
||||
// Each of these will replace the contents of the receiver with the bitvector
|
||||
// in the parameter array. The number of bits is changed to nbits. If nbits
|
||||
// is smaller than fNBits, the receiver will NOT be compacted.
|
||||
|
||||
void Set(unsigned int nbits, const char* array);
|
||||
// void Set(unsigned int nbits, const unsigned char *array) { Set(nbits, (const char*)array); }
|
||||
// void Set(unsigned int nbits, const short *array);
|
||||
//void Set(unsigned int nbits, const unsigned short *array) { Set(nbits, (const short*)array); }
|
||||
void Set(unsigned int nbits, const int* array);
|
||||
// void Set(unsigned int nbits, const unsigned int *array) { Set(nbits, (const int*)array); }
|
||||
|
||||
//----- Optimized getters
|
||||
// Each of these will replace the contents of the parameter array with the
|
||||
// bits in the receiver. The parameter array must be large enough to hold
|
||||
// all of the bits in the receiver.
|
||||
// Note on semantics: any bits in the parameter array that go beyond the
|
||||
// number of the bits in the receiver will have an unspecified value. For
|
||||
// example, if you call Get(Int*) with an array of one integer and the UBits
|
||||
// object has less than 32 bits, then the remaining bits in the integer will
|
||||
// have an unspecified value.
|
||||
void Get(char* array) const;
|
||||
// void Get(unsigned char *array) const { Get((char*)array); }
|
||||
// void Get(short *array) const;
|
||||
// void Get(unsigned short *array) const { Get((short*)array); }
|
||||
void Get(int* array) const;
|
||||
// void Get(unsigned int *array) const { Get((int*)array); }
|
||||
|
||||
//----- Utilities
|
||||
void Clear();
|
||||
void Compact(); // Reduce the space used.
|
||||
|
||||
|
||||
unsigned int GetNbits() const
|
||||
{
|
||||
return fNBits;
|
||||
}
|
||||
unsigned int GetNbytes() const
|
||||
{
|
||||
return fNBytes;
|
||||
}
|
||||
|
||||
/*
|
||||
unsigned int CounUBits(unsigned int startBit=0) const ; // return number of bits set to 1
|
||||
unsigned int FirstNullBit(unsigned int startBit=0) const;
|
||||
unsigned int FirstSetBit(unsigned int startBit=0) const;
|
||||
*/
|
||||
|
||||
// bool operator==(const UBits &other) const;
|
||||
// bool operator!=(const UBits &other) const { return !(*this==other); }
|
||||
|
||||
void Print() const; // to show the list of active bits
|
||||
void Output(std::ostream&) const;
|
||||
};
|
||||
|
||||
/*
|
||||
inline UBits operator&(const UBits& lhs, const UBits& rhs)
|
||||
{
|
||||
UBits result(lhs);
|
||||
result &= rhs;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline UBits operator|(const UBits& lhs, const UBits& rhs)
|
||||
{
|
||||
UBits result(lhs);
|
||||
result |= rhs;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline UBits operator^(const UBits& lhs, const UBits& rhs)
|
||||
{
|
||||
UBits result(lhs);
|
||||
result ^= rhs;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline std::ostream &operator<<(std::ostream& os, const UBits& rhs)
|
||||
{
|
||||
rhs.Output(os); return os;
|
||||
}
|
||||
*/
|
||||
|
||||
// inline functions...
|
||||
|
||||
inline void UBits::SetBitNumber(unsigned int bitnumber, bool value)
|
||||
{
|
||||
// Set bit number 'bitnumber' to be value
|
||||
if (bitnumber >= fNBits)
|
||||
{
|
||||
unsigned int new_size = (bitnumber / 8) + 1;
|
||||
if (new_size > fNBytes)
|
||||
{
|
||||
if (new_size < 100 * 1024 * 1024)
|
||||
new_size *= 2;
|
||||
unsigned char* old_location = fAllBits;
|
||||
fAllBits = new unsigned char[new_size];
|
||||
std::memcpy(fAllBits, old_location, fNBytes);
|
||||
std::memset(fAllBits + fNBytes , 0, new_size - fNBytes);
|
||||
fNBytes = new_size;
|
||||
delete [] old_location;
|
||||
}
|
||||
fNBits = bitnumber + 1;
|
||||
}
|
||||
unsigned int loc = bitnumber / 8;
|
||||
unsigned char bit = bitnumber % 8;
|
||||
if (value)
|
||||
fAllBits[loc] |= (1 << bit);
|
||||
else
|
||||
fAllBits[loc] &= (0xFF ^ (1 << bit));
|
||||
}
|
||||
|
||||
inline bool UBits::TestBitNumber(unsigned int bitnumber) const
|
||||
{
|
||||
// Return the current value of the bit
|
||||
|
||||
if (bitnumber >= fNBits) return false;
|
||||
unsigned int loc = bitnumber / 8;
|
||||
unsigned char value = fAllBits[loc];
|
||||
unsigned char bit = bitnumber % 8;
|
||||
bool result = (value & (1 << bit)) != 0;
|
||||
return result;
|
||||
// short: return 0 != (fAllBits[bitnumber/8] & (1<< (bitnumber%8)));
|
||||
}
|
||||
|
||||
inline void UBits::ResetBitNumber(unsigned int bitnumber)
|
||||
{
|
||||
SetBitNumber(bitnumber, false);
|
||||
}
|
||||
|
||||
inline bool UBits::operator[](unsigned int bitnumber) const
|
||||
{
|
||||
return TestBitNumber(bitnumber);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,156 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UBox
|
||||
//
|
||||
// Class description:
|
||||
//
|
||||
// A simple box defined by half-lengths on the three axis.
|
||||
// The center of the box matches the origin of the local reference frame.
|
||||
//
|
||||
// 10.06.11 J.Apostolakis, G.Cosmo, A.Gheata
|
||||
// Created from original implementation in Geant4 and ROOT
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#ifndef USOLIDS_UBox
|
||||
#define USOLIDS_UBox
|
||||
|
||||
#ifndef USOLIDS_VUSolid
|
||||
#include "VUSolid.hh"
|
||||
#endif
|
||||
|
||||
#ifndef USOLIDS_UUtils
|
||||
#include "UUtils.hh"
|
||||
#endif
|
||||
|
||||
class UBox : public VUSolid
|
||||
{
|
||||
|
||||
public:
|
||||
UBox() : VUSolid(), fDx(0), fDy(0), fDz(0),fCubicVolume(0.), fSurfaceArea(0.) {}
|
||||
UBox(const std::string& name, double dx, double dy, double dz);
|
||||
virtual ~UBox();
|
||||
|
||||
UBox(const UBox& rhs);
|
||||
UBox& operator=(const UBox& rhs);
|
||||
|
||||
// Copy constructor and assignment operator
|
||||
|
||||
void Set(double dx, double dy, double dz);
|
||||
void Set(const UVector3& vec);
|
||||
|
||||
// Accessors and modifiers
|
||||
|
||||
|
||||
|
||||
inline double GetXHalfLength() const;
|
||||
inline double GetYHalfLength() const;
|
||||
inline double GetZHalfLength() const;
|
||||
|
||||
void SetXHalfLength(double dx);
|
||||
void SetYHalfLength(double dy);
|
||||
void SetZHalfLength(double dz);
|
||||
|
||||
|
||||
// Navigation methods
|
||||
EnumInside Inside(const UVector3& aPoint) const;
|
||||
|
||||
double SafetyFromInside(const UVector3& aPoint,
|
||||
bool aAccurate = false) const;
|
||||
double SafetyFromOutside(const UVector3& aPoint,
|
||||
bool aAccurate = false) const;
|
||||
double DistanceToIn(const UVector3& aPoint,
|
||||
const UVector3& aDirection,
|
||||
// UVector3 &aNormalVector,
|
||||
|
||||
double aPstep = UUtils::kInfinity) const;
|
||||
|
||||
double DistanceToOut(const UVector3& aPoint,
|
||||
const UVector3& aDirection,
|
||||
UVector3& aNormalVector,
|
||||
bool& aConvex,
|
||||
double aPstep = UUtils::kInfinity) const;
|
||||
bool Normal(const UVector3& aPoint, UVector3& aNormal) const;
|
||||
// void Extent ( EAxisType aAxis, double &aMin, double &aMax ) const;
|
||||
void Extent(UVector3& aMin, UVector3& aMax) const;
|
||||
inline double Capacity();
|
||||
inline double SurfaceArea();
|
||||
VUSolid* Clone() const
|
||||
{
|
||||
return new UBox(GetName(), fDx, fDy, fDz);
|
||||
}
|
||||
UGeometryType GetEntityType() const;
|
||||
|
||||
void ComputeBBox(UBBox* /*aBox*/, bool /*aStore = false*/) {}
|
||||
|
||||
//G4Visualisation
|
||||
void GetParametersList(int, double* aArray) const
|
||||
{
|
||||
aArray[0] = GetXHalfLength();
|
||||
aArray[1] = GetYHalfLength();
|
||||
aArray[2] = GetZHalfLength();
|
||||
}
|
||||
|
||||
UVector3 GetPointOnSurface() const;
|
||||
|
||||
std::ostream& StreamInfo(std::ostream& os) const;
|
||||
|
||||
|
||||
private:
|
||||
double fDx; // Half-length on X
|
||||
double fDy; // Half-length on Y
|
||||
double fDz; // Half-length on Z
|
||||
double fCubicVolume; // Cubic Volume
|
||||
double fSurfaceArea; // Surface Area
|
||||
|
||||
};
|
||||
|
||||
|
||||
inline double UBox::GetXHalfLength() const
|
||||
{
|
||||
return fDx;
|
||||
}
|
||||
inline double UBox::GetYHalfLength() const
|
||||
{
|
||||
return fDy;
|
||||
}
|
||||
inline double UBox::GetZHalfLength() const
|
||||
{
|
||||
return fDz;
|
||||
}
|
||||
|
||||
inline double UBox::Capacity()
|
||||
{
|
||||
if (fCubicVolume != 0.)
|
||||
{
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
fCubicVolume = 8 * fDx * fDy * fDz;
|
||||
}
|
||||
return fCubicVolume;
|
||||
}
|
||||
|
||||
inline double UBox::SurfaceArea()
|
||||
{
|
||||
if (fSurfaceArea != 0.)
|
||||
{
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
fSurfaceArea = 8 * (fDx * fDy + fDx * fDz + fDy * fDz);
|
||||
}
|
||||
return fSurfaceArea;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,302 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UCons
|
||||
//
|
||||
// Class description:
|
||||
//
|
||||
// A UCons is, in the general case, a Phi segment of a cone, with
|
||||
// half-length fDz, inner and outer radii specified at -fDz and +fDz.
|
||||
// The Phi segment is described by a starting fSPhi angle, and the
|
||||
// +fDPhi delta angle for the shape.
|
||||
// If the delta angle is >=2*UUtils::kPi, the shape is treated as
|
||||
// continuous in Phi
|
||||
//
|
||||
// Member Data:
|
||||
//
|
||||
// fRmin1 inside radius at -fDz
|
||||
// fRmin2 inside radius at +fDz
|
||||
// fRmax1 outside radius at -fDz
|
||||
// fRmax2 outside radius at +fDz
|
||||
// fDz half length in z
|
||||
//
|
||||
// fSPhi starting angle of the segment in radians
|
||||
// fDPhi delta angle of the segment in radians
|
||||
//
|
||||
// fPhiFullCone Boolean variable used for indicate the Phi Section
|
||||
//
|
||||
// Note:
|
||||
// Internally fSPhi & fDPhi are adjusted so that fDPhi<=2PI,
|
||||
// and fDPhi+fSPhi<=2PI. This enables simpler comparisons to be
|
||||
// made with (say) Phi of a point.
|
||||
//
|
||||
// 19.10.12 Marek Gayer
|
||||
// Created from original implementation in Geant4
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#ifndef UCons_HH
|
||||
#define UCons_HH
|
||||
|
||||
#include "VUSolid.hh"
|
||||
|
||||
class UCons : public VUSolid
|
||||
{
|
||||
public: // with description
|
||||
|
||||
UCons(const std::string& pName,
|
||||
double pRmin1, double pRmax1,
|
||||
double pRmin2, double pRmax2,
|
||||
double pDz,
|
||||
double pSPhi, double pDPhi);
|
||||
//
|
||||
// Constructs a cone with the given name and dimensions
|
||||
|
||||
~UCons() ;
|
||||
//
|
||||
// Destructor
|
||||
|
||||
// Accessors
|
||||
|
||||
inline double GetInnerRadiusMinusZ() const;
|
||||
inline double GetOuterRadiusMinusZ() const;
|
||||
inline double GetInnerRadiusPlusZ() const;
|
||||
inline double GetOuterRadiusPlusZ() const;
|
||||
inline double GetZHalfLength() const;
|
||||
inline double GetStartPhiAngle() const;
|
||||
inline double GetDeltaPhiAngle() const;
|
||||
|
||||
// Modifiers
|
||||
|
||||
inline void SetInnerRadiusMinusZ(double Rmin1);
|
||||
inline void SetOuterRadiusMinusZ(double Rmax1);
|
||||
inline void SetInnerRadiusPlusZ(double Rmin2);
|
||||
inline void SetOuterRadiusPlusZ(double Rmax2);
|
||||
inline void SetZHalfLength(double newDz);
|
||||
inline void SetStartPhiAngle(double newSPhi, bool trig = true);
|
||||
inline void SetDeltaPhiAngle(double newDPhi);
|
||||
|
||||
// Other methods for solid
|
||||
|
||||
inline double GetCubicVolume();
|
||||
inline double GetSurfaceArea();
|
||||
|
||||
|
||||
// inline VUSolid::EnumInside Inside( const UVector3& p ) const;
|
||||
|
||||
bool Normal(const UVector3& p, UVector3& n) const;
|
||||
|
||||
double DistanceToIn(const UVector3& p, const UVector3& v, double aPstep = UUtils::kInfinity) const;
|
||||
|
||||
double SafetyFromOutside(const UVector3& p, bool precise) const;
|
||||
|
||||
|
||||
|
||||
double DistanceToOut(const UVector3& aPoint,
|
||||
const UVector3& aDirection,
|
||||
UVector3& aNormalVector,
|
||||
bool& aConvex,
|
||||
double aPstep = UUtils::kInfinity) const;
|
||||
|
||||
double SafetyFromInside(const UVector3& p, bool precise) const;
|
||||
|
||||
UGeometryType GetEntityType() const;
|
||||
|
||||
UVector3 GetPointOnSurface() const;
|
||||
|
||||
VUSolid* Clone() const;
|
||||
|
||||
std::ostream& StreamInfo(std::ostream& os) const;
|
||||
|
||||
// void Extent (EAxisType aAxis, double &aMin, double &aMax) const;
|
||||
void Extent(UVector3& aMin, UVector3& aMax) const;
|
||||
|
||||
virtual void GetParametersList(int /*aNumber*/, double* /*aArray*/) const;
|
||||
|
||||
virtual void ComputeBBox(UBBox* /*aBox*/, bool /*aStore = false*/) {}
|
||||
|
||||
// Visualisation functions
|
||||
|
||||
|
||||
inline VUSolid::EnumInside Inside(const UVector3& p) const
|
||||
{
|
||||
double r2, rl, rh, pPhi, tolRMin, tolRMax; // rh2, rl2;
|
||||
VUSolid::EnumInside in;
|
||||
static const double halfCarTolerance = VUSolid::Tolerance() * 0.5;
|
||||
static const double halfRadTolerance = kRadTolerance * 0.5;
|
||||
static const double halfAngTolerance = kAngTolerance * 0.5;
|
||||
|
||||
if (std::fabs(p.z) > fDz + halfCarTolerance)
|
||||
{
|
||||
return in = eOutside;
|
||||
}
|
||||
else if (std::fabs(p.z) >= fDz - halfCarTolerance)
|
||||
{
|
||||
in = eSurface;
|
||||
}
|
||||
else
|
||||
{
|
||||
in = eInside;
|
||||
}
|
||||
|
||||
r2 = p.x * p.x + p.y * p.y;
|
||||
rl = 0.5 * (fRmin2 * (p.z + fDz) + fRmin1 * (fDz - p.z)) / fDz;
|
||||
rh = 0.5 * (fRmax2 * (p.z + fDz) + fRmax1 * (fDz - p.z)) / fDz;
|
||||
|
||||
// rh2 = rh*rh;
|
||||
|
||||
tolRMin = rl - halfRadTolerance;
|
||||
if (tolRMin < 0)
|
||||
{
|
||||
tolRMin = 0;
|
||||
}
|
||||
tolRMax = rh + halfRadTolerance;
|
||||
|
||||
if ((r2 < tolRMin * tolRMin) || (r2 > tolRMax * tolRMax))
|
||||
{
|
||||
return in = eOutside;
|
||||
}
|
||||
|
||||
if (rl)
|
||||
{
|
||||
tolRMin = rl + halfRadTolerance;
|
||||
}
|
||||
else
|
||||
{
|
||||
tolRMin = 0.0;
|
||||
}
|
||||
tolRMax = rh - halfRadTolerance;
|
||||
|
||||
if (in == eInside) // else it's eSurface already
|
||||
{
|
||||
if ((r2 < tolRMin * tolRMin) || (r2 >= tolRMax * tolRMax))
|
||||
{
|
||||
in = eSurface;
|
||||
}
|
||||
}
|
||||
if (!fPhiFullCone && ((p.x != 0.0) || (p.y != 0.0)))
|
||||
{
|
||||
pPhi = std::atan2(p.y, p.x);
|
||||
|
||||
if (pPhi < fSPhi - halfAngTolerance)
|
||||
{
|
||||
pPhi += 2 * UUtils::kPi;
|
||||
}
|
||||
else if (pPhi > fSPhi + fDPhi + halfAngTolerance)
|
||||
{
|
||||
pPhi -= 2 * UUtils::kPi;
|
||||
}
|
||||
|
||||
if ((pPhi < fSPhi - halfAngTolerance) ||
|
||||
(pPhi > fSPhi + fDPhi + halfAngTolerance))
|
||||
{
|
||||
return in = eOutside;
|
||||
}
|
||||
|
||||
else if (in == eInside) // else it's eSurface anyway already
|
||||
{
|
||||
if ((pPhi < fSPhi + halfAngTolerance) ||
|
||||
(pPhi > fSPhi + fDPhi - halfAngTolerance))
|
||||
{
|
||||
in = eSurface;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!fPhiFullCone)
|
||||
{
|
||||
in = eSurface;
|
||||
}
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
public: // without description
|
||||
|
||||
UCons();
|
||||
//
|
||||
// Fake default constructor for usage restricted to direct object
|
||||
// persistency for clients requiring preallocation of memory for
|
||||
// persistifiable objects.
|
||||
|
||||
UCons(const UCons& rhs);
|
||||
UCons& operator=(const UCons& rhs);
|
||||
// Copy constructor and assignment operator.
|
||||
|
||||
// Old access functions
|
||||
|
||||
inline double GetRmin1() const;
|
||||
inline double GetRmax1() const;
|
||||
inline double GetRmin2() const;
|
||||
inline double GetRmax2() const;
|
||||
inline double GetDz() const;
|
||||
inline double GetSPhi() const;
|
||||
inline double GetDPhi() const;
|
||||
|
||||
private:
|
||||
|
||||
double fCubicVolume, fSurfaceArea;
|
||||
|
||||
inline double Capacity();
|
||||
inline double SurfaceArea();
|
||||
|
||||
inline void Initialize();
|
||||
//
|
||||
// Reset relevant values to zero
|
||||
|
||||
inline void CheckSPhiAngle(double sPhi);
|
||||
inline void CheckDPhiAngle(double dPhi);
|
||||
inline void CheckPhiAngles(double sPhi, double dPhi);
|
||||
//
|
||||
// Reset relevant flags and angle values
|
||||
|
||||
inline void InitializeTrigonometry();
|
||||
//
|
||||
// Recompute relevant trigonometric values and cache them
|
||||
|
||||
UVector3 ApproxSurfaceNormal(const UVector3& p) const;
|
||||
//
|
||||
// Algorithm for SurfaceNormal() following the original
|
||||
// specification for points not on the surface
|
||||
|
||||
private:
|
||||
|
||||
// Used by distanceToOut
|
||||
//
|
||||
enum ESide {kNull, kRMin, kRMax, kSPhi, kEPhi, kPZ, kMZ};
|
||||
|
||||
// used by normal
|
||||
//
|
||||
enum ENorm {kNRMin, kNRMax, kNSPhi, kNEPhi, kNZ};
|
||||
|
||||
double kRadTolerance, kAngTolerance;
|
||||
//
|
||||
// Radial and angular tolerances
|
||||
|
||||
double fRmin1, fRmin2, fRmax1, fRmax2, fDz, fSPhi, fDPhi;
|
||||
//
|
||||
// Radial and angular dimensions
|
||||
|
||||
double sinCPhi, cosCPhi, cosHDPhiOT, cosHDPhiIT,
|
||||
sinSPhi, cosSPhi, sinEPhi, cosEPhi;
|
||||
//
|
||||
// Cached trigonometric values
|
||||
|
||||
bool fPhiFullCone;
|
||||
|
||||
double secRMin, tanRMin, tanRMax, secRMax;
|
||||
|
||||
// double fSinPhi;
|
||||
|
||||
//
|
||||
// Flag for identification of section or full cone
|
||||
};
|
||||
|
||||
#include "UCons.icc"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,294 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UCons.icc
|
||||
//
|
||||
// Implementation of inline methods of UCons
|
||||
//
|
||||
// 19.10.12 Marek Gayer
|
||||
// Created from original implementation in Geant4
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
inline
|
||||
double UCons::GetInnerRadiusMinusZ() const
|
||||
{
|
||||
return fRmin1 ;
|
||||
}
|
||||
|
||||
inline
|
||||
double UCons::GetOuterRadiusMinusZ() const
|
||||
{
|
||||
return fRmax1 ;
|
||||
}
|
||||
|
||||
inline
|
||||
double UCons::GetInnerRadiusPlusZ() const
|
||||
{
|
||||
return fRmin2 ;
|
||||
}
|
||||
|
||||
inline
|
||||
double UCons::GetOuterRadiusPlusZ() const
|
||||
{
|
||||
return fRmax2 ;
|
||||
}
|
||||
|
||||
inline
|
||||
double UCons::GetZHalfLength() const
|
||||
{
|
||||
return fDz ;
|
||||
}
|
||||
|
||||
inline
|
||||
double UCons::GetStartPhiAngle() const
|
||||
{
|
||||
return fSPhi ;
|
||||
}
|
||||
|
||||
inline
|
||||
double UCons::GetDeltaPhiAngle() const
|
||||
{
|
||||
return fDPhi;
|
||||
}
|
||||
|
||||
inline
|
||||
void UCons::Initialize()
|
||||
{
|
||||
fCubicVolume = 0.;
|
||||
fSurfaceArea = 0.;
|
||||
|
||||
tanRMin = (fRmin2 - fRmin1) * 0.5 / fDz;
|
||||
secRMin = std::sqrt(1.0 + tanRMin * tanRMin);
|
||||
|
||||
tanRMax = (fRmax2 - fRmax1) * 0.5 / fDz;
|
||||
secRMax = std::sqrt(1.0 + tanRMax * tanRMax);
|
||||
}
|
||||
|
||||
inline
|
||||
void UCons::InitializeTrigonometry()
|
||||
{
|
||||
double hDPhi = 0.5 * fDPhi; // half delta phi
|
||||
double cPhi = fSPhi + hDPhi;
|
||||
double ePhi = fSPhi + fDPhi;
|
||||
|
||||
sinCPhi = std::sin(cPhi);
|
||||
cosCPhi = std::cos(cPhi);
|
||||
cosHDPhiIT = std::cos(hDPhi - 0.5 * kAngTolerance); // inner/outer tol half dphi
|
||||
cosHDPhiOT = std::cos(hDPhi + 0.5 * kAngTolerance);
|
||||
sinSPhi = std::sin(fSPhi);
|
||||
cosSPhi = std::cos(fSPhi);
|
||||
sinEPhi = std::sin(ePhi);
|
||||
cosEPhi = std::cos(ePhi);
|
||||
}
|
||||
|
||||
inline void UCons::CheckSPhiAngle(double sPhi)
|
||||
{
|
||||
// Ensure fSphi in 0-2PI or -2PI-0 range if shape crosses 0
|
||||
|
||||
if (sPhi < 0)
|
||||
{
|
||||
fSPhi = 2 * UUtils::kPi - std::fmod(std::fabs(sPhi), 2 * UUtils::kPi);
|
||||
}
|
||||
else
|
||||
{
|
||||
fSPhi = std::fmod(sPhi, 2 * UUtils::kPi) ;
|
||||
}
|
||||
if (fSPhi + fDPhi > 2 * UUtils::kPi)
|
||||
{
|
||||
fSPhi -= 2 * UUtils::kPi ;
|
||||
}
|
||||
}
|
||||
|
||||
inline void UCons::CheckDPhiAngle(double dPhi)
|
||||
{
|
||||
fPhiFullCone = true;
|
||||
if (dPhi >= 2 * UUtils::kPi - kAngTolerance * 0.5)
|
||||
{
|
||||
fDPhi = 2 * UUtils::kPi;
|
||||
fSPhi = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
fPhiFullCone = false;
|
||||
if (dPhi > 0)
|
||||
{
|
||||
fDPhi = dPhi;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Invalid dphi." << std::endl
|
||||
<< "Negative or zero delta-Phi (" << dPhi << ") in solid: "
|
||||
<< GetName();
|
||||
UUtils::Exception("UCons::CheckDPhiAngle()", "GeomSolids0002",
|
||||
FatalErrorInArguments, 1, message.str().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void UCons::CheckPhiAngles(double sPhi, double dPhi)
|
||||
{
|
||||
CheckDPhiAngle(dPhi);
|
||||
if ((fDPhi < 2 * UUtils::kPi) && (sPhi))
|
||||
{
|
||||
CheckSPhiAngle(sPhi);
|
||||
}
|
||||
InitializeTrigonometry();
|
||||
}
|
||||
|
||||
inline
|
||||
void UCons::SetInnerRadiusMinusZ(double Rmin1)
|
||||
{
|
||||
fRmin1 = Rmin1 ;
|
||||
Initialize();
|
||||
}
|
||||
|
||||
inline
|
||||
void UCons::SetOuterRadiusMinusZ(double Rmax1)
|
||||
{
|
||||
fRmax1 = Rmax1 ;
|
||||
Initialize();
|
||||
}
|
||||
|
||||
inline
|
||||
void UCons::SetInnerRadiusPlusZ(double Rmin2)
|
||||
{
|
||||
fRmin2 = Rmin2 ;
|
||||
Initialize();
|
||||
}
|
||||
|
||||
inline
|
||||
void UCons::SetOuterRadiusPlusZ(double Rmax2)
|
||||
{
|
||||
fRmax2 = Rmax2 ;
|
||||
Initialize();
|
||||
}
|
||||
|
||||
inline
|
||||
void UCons::SetZHalfLength(double newDz)
|
||||
{
|
||||
fDz = newDz ;
|
||||
Initialize();
|
||||
}
|
||||
|
||||
inline
|
||||
void UCons::SetStartPhiAngle(double newSPhi, bool compute)
|
||||
{
|
||||
// Flag 'compute' can be used to explicitely avoid recomputation of
|
||||
// trigonometry in case SetDeltaPhiAngle() is invoked afterwards
|
||||
|
||||
CheckSPhiAngle(newSPhi);
|
||||
fPhiFullCone = false;
|
||||
if (compute)
|
||||
{
|
||||
InitializeTrigonometry();
|
||||
}
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void UCons::SetDeltaPhiAngle(double newDPhi)
|
||||
{
|
||||
CheckPhiAngles(fSPhi, newDPhi);
|
||||
Initialize();
|
||||
}
|
||||
|
||||
// Old access methods ...
|
||||
|
||||
inline
|
||||
double UCons::GetRmin1() const
|
||||
{
|
||||
return GetInnerRadiusMinusZ();
|
||||
}
|
||||
|
||||
inline
|
||||
double UCons::GetRmax1() const
|
||||
{
|
||||
return GetOuterRadiusMinusZ();
|
||||
}
|
||||
|
||||
inline
|
||||
double UCons::GetRmin2() const
|
||||
{
|
||||
return GetInnerRadiusPlusZ();
|
||||
}
|
||||
|
||||
inline
|
||||
double UCons::GetRmax2() const
|
||||
{
|
||||
return GetOuterRadiusPlusZ();
|
||||
}
|
||||
|
||||
inline
|
||||
double UCons::GetDz() const
|
||||
{
|
||||
return GetZHalfLength();
|
||||
}
|
||||
|
||||
inline
|
||||
double UCons::GetSPhi() const
|
||||
{
|
||||
return GetStartPhiAngle();
|
||||
}
|
||||
|
||||
inline
|
||||
double UCons::GetDPhi() const
|
||||
{
|
||||
return GetDeltaPhiAngle();
|
||||
}
|
||||
|
||||
inline
|
||||
double UCons::Capacity()
|
||||
{
|
||||
if (fCubicVolume != 0.)
|
||||
{
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
double Rmean, rMean, deltaR, deltar;
|
||||
|
||||
Rmean = 0.5 * (fRmax1 + fRmax2);
|
||||
deltaR = fRmax1 - fRmax2;
|
||||
|
||||
rMean = 0.5 * (fRmin1 + fRmin2);
|
||||
deltar = fRmin1 - fRmin2;
|
||||
fCubicVolume = fDPhi * fDz * (Rmean * Rmean - rMean * rMean
|
||||
+ (deltaR * deltaR - deltar * deltar) / 12);
|
||||
}
|
||||
return fCubicVolume;
|
||||
}
|
||||
|
||||
inline
|
||||
double UCons::SurfaceArea()
|
||||
{
|
||||
if (fSurfaceArea != 0.)
|
||||
{
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
double mmin, mmax, dmin, dmax;
|
||||
|
||||
mmin = (fRmin1 + fRmin2) * 0.5;
|
||||
mmax = (fRmax1 + fRmax2) * 0.5;
|
||||
dmin = (fRmin2 - fRmin1);
|
||||
dmax = (fRmax2 - fRmax1);
|
||||
|
||||
fSurfaceArea = fDPhi * (mmin * std::sqrt(dmin * dmin + 4 * fDz * fDz)
|
||||
+ mmax * std::sqrt(dmax * dmax + 4 * fDz * fDz)
|
||||
+ 0.5 * (fRmax1 * fRmax1 - fRmin1 * fRmin1
|
||||
+ fRmax2 * fRmax2 - fRmin2 * fRmin2));
|
||||
if (!fPhiFullCone)
|
||||
{
|
||||
fSurfaceArea = fSurfaceArea + 4 * fDz * (mmax - mmin);
|
||||
}
|
||||
}
|
||||
return fSurfaceArea;
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UEnclosingCylinder
|
||||
//
|
||||
// Class description:
|
||||
//
|
||||
// Definition of a utility class for quickly deciding if a point
|
||||
// is clearly outside a polyhedra or polycone or deciding if
|
||||
// a trajectory is clearly going to miss those shapes.
|
||||
//
|
||||
// 19.10.12 Marek Gayer
|
||||
// Created from original implementation in Geant4
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#ifndef UEnclosingCylinder_hh
|
||||
#define UEnclosingCylinder_hh
|
||||
|
||||
#include "UTypes.hh"
|
||||
#include "UTubs.hh"
|
||||
|
||||
class UReduciblePolygon;
|
||||
|
||||
class UEnclosingCylinder
|
||||
{
|
||||
public: // with description
|
||||
|
||||
UEnclosingCylinder(/*const UReduciblePolygon *rz*/ double r, double lo, double hi,
|
||||
bool phiIsOpen,
|
||||
double startPhi, double totalPhi);
|
||||
~UEnclosingCylinder();
|
||||
|
||||
bool MustBeOutside(const UVector3& p) const;
|
||||
// Decide very rapidly if the point is outside the cylinder.
|
||||
// If one is not certain, return false.
|
||||
|
||||
bool ShouldMiss(const UVector3& p, const UVector3& v) const;
|
||||
// Decide very rapidly if the trajectory is going to miss the cylinder.
|
||||
// If one is not sure, return false.
|
||||
|
||||
double DistanceTo(const UVector3& p, const UVector3& v) const;
|
||||
|
||||
double SafetyFromOutside(const UVector3& p) const;
|
||||
|
||||
public: // without description
|
||||
|
||||
void Extent(UVector3& aMin, UVector3& aMax) const;
|
||||
|
||||
double radius; // radius of our cylinder
|
||||
|
||||
protected:
|
||||
|
||||
double zLo, zHi; // z extent
|
||||
|
||||
bool phiIsOpen; // true if there is a phi segment
|
||||
double startPhi, // for isPhiOpen==true, starting of phi segment
|
||||
totalPhi; // for isPhiOpen==true, size of phi segment
|
||||
|
||||
double rx1, ry1,
|
||||
dx1, dy1;
|
||||
double rx2, ry2,
|
||||
dx2, dy2;
|
||||
|
||||
bool concave; // true, if x/y Cross section is concave
|
||||
|
||||
UTubs* tube;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,147 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UGenericPolycone
|
||||
//
|
||||
// Class description:
|
||||
//
|
||||
// Implementing a CSG-like type "PCON" volume with possibility of
|
||||
// specifying also 'decreasing' Z sections:
|
||||
//
|
||||
// UGenericPolycone( const std::string& name,
|
||||
// double phiStart, // initial phi starting angle
|
||||
// double phiTotal, // total phi angle
|
||||
// int numRZ, // number corners in r,z space
|
||||
// const double r[], // r coordinate of these corners
|
||||
// const double z[]) // z coordinate of these corners
|
||||
//
|
||||
// 19.10.13 Tatiana Nikitina
|
||||
// Created from original implementation in Geant4
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#ifndef UGenericPolycone_hh
|
||||
#define UGenericPolycone_hh
|
||||
|
||||
#include "UVCSGfaceted.hh"
|
||||
#include "UPolyconeSide.hh"
|
||||
|
||||
class UEnclosingCylinder;
|
||||
class UReduciblePolygon;
|
||||
class UVCSGface;
|
||||
|
||||
class UGenericPolycone: public UVCSGfaceted
|
||||
{
|
||||
|
||||
public: // with description
|
||||
|
||||
UGenericPolycone(const std::string& name,
|
||||
double phiStart, // initial phi starting angle
|
||||
double phiTotal, // total phi angle
|
||||
int numZPlanes, // number of z planes
|
||||
const double zPlane[], // position of z planes
|
||||
const double rInner[], // tangent distance to inner surface
|
||||
const double rOuter[]); // tangent distance to outer surface
|
||||
|
||||
UGenericPolycone(const std::string& name,
|
||||
double phiStart, // initial phi starting angle
|
||||
double phiTotal, // total phi angle
|
||||
int numRZ, // number corners in r,z space
|
||||
const double r[], // r coordinate of these corners
|
||||
const double z[]); // z coordinate of these corners
|
||||
|
||||
virtual ~UGenericPolycone();
|
||||
|
||||
// Methods for solid
|
||||
|
||||
VUSolid::EnumInside Inside(const UVector3& p) const;
|
||||
double DistanceToIn(const UVector3& p, const UVector3& v, double aPstep = UUtils::kInfinity) const;
|
||||
// double SafetyFromOutside( const UVector3 &p, bool aAccurate=false) const;
|
||||
|
||||
UVector3 GetPointOnSurface() const;
|
||||
|
||||
/*
|
||||
void ComputeDimensions( UVPVParameterisation* p,
|
||||
const int n,
|
||||
const UVPhysicalVolume* pRep );
|
||||
*/
|
||||
|
||||
UGeometryType GetEntityType() const;
|
||||
|
||||
VUSolid* Clone() const;
|
||||
|
||||
std::ostream& StreamInfo(std::ostream& os) const;
|
||||
|
||||
|
||||
bool Reset();
|
||||
|
||||
// Accessors
|
||||
|
||||
inline double GetStartPhi() const;
|
||||
inline double GetEndPhi() const;
|
||||
inline bool IsOpen() const;
|
||||
inline int GetNumRZCorner() const;
|
||||
inline UPolyconeSideRZ GetCorner(int index) const;
|
||||
|
||||
|
||||
public: // without description
|
||||
|
||||
//UPolycone(__void__&);
|
||||
// Fake default constructor for usage restricted to direct object
|
||||
// persistency for clients requiring preallocation of memory for
|
||||
// persistifiable objects.
|
||||
|
||||
UGenericPolycone(const UGenericPolycone& source);
|
||||
UGenericPolycone& operator=(const UGenericPolycone& source);
|
||||
// Copy constructor and assignment operator.
|
||||
|
||||
protected: // without description
|
||||
|
||||
// Generic initializer, called by all constructors
|
||||
|
||||
|
||||
void Create(double phiStart, // initial phi starting angle
|
||||
double phiTotal, // total phi angle
|
||||
UReduciblePolygon* rz); // r/z coordinate of these corners
|
||||
|
||||
void CopyStuff(const UGenericPolycone& source);
|
||||
|
||||
// Methods for random point generation
|
||||
|
||||
|
||||
|
||||
void GetParametersList(int /*aNumber*/, double* /*aArray*/) const {}
|
||||
|
||||
void ComputeBBox(UBBox* /*aBox*/, bool /*aStore*/)
|
||||
{
|
||||
// Computes bounding box.
|
||||
std::cout << "ComputeBBox - Not implemented" << std::endl;
|
||||
}
|
||||
|
||||
void Extent(UVector3& aMin, UVector3& aMax) const;
|
||||
|
||||
protected: // without description
|
||||
|
||||
// Here are our parameters
|
||||
|
||||
double startPhi; // Starting phi value (0 < phiStart < 2pi)
|
||||
double endPhi; // end phi value (0 < endPhi-phiStart < 2pi)
|
||||
bool phiIsOpen; // true if there is a phi segment
|
||||
int numCorner; // number RZ points
|
||||
UPolyconeSideRZ* corners; // corner r,z points
|
||||
|
||||
// Our quick test
|
||||
|
||||
UEnclosingCylinder* enclosingCylinder;
|
||||
|
||||
};
|
||||
|
||||
#include "UGenericPolycone.icc"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UGenericPolycone.icc
|
||||
//
|
||||
// Implementation of inline methods of UGenericPolycone
|
||||
//
|
||||
// 19.10.13 Tatiana Nikitina
|
||||
// Created from original implementation in Geant4
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
inline
|
||||
double UGenericPolycone::GetStartPhi() const
|
||||
{
|
||||
return startPhi;
|
||||
}
|
||||
|
||||
inline
|
||||
double UGenericPolycone::GetEndPhi() const
|
||||
{
|
||||
return endPhi;
|
||||
}
|
||||
|
||||
inline
|
||||
bool UGenericPolycone::IsOpen() const
|
||||
{
|
||||
return phiIsOpen;
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
int UGenericPolycone::GetNumRZCorner() const
|
||||
{
|
||||
return numCorner;
|
||||
}
|
||||
|
||||
inline
|
||||
UPolyconeSideRZ UGenericPolycone::GetCorner(int index) const
|
||||
{
|
||||
return corners[index];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UIntersectingCone
|
||||
//
|
||||
// Class description:
|
||||
//
|
||||
// Utility class which calculates the intersection
|
||||
// of an arbitrary line with a fixed cone
|
||||
//
|
||||
// 19.02.13 Marek Gayer
|
||||
// Created from original implementation in Geant4
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#ifndef UIntersectingCone_hh
|
||||
#define UIntersectingCone_hh
|
||||
|
||||
#include "UTypes.hh"
|
||||
|
||||
class UIntersectingCone
|
||||
{
|
||||
public:
|
||||
|
||||
UIntersectingCone(const double r[2], const double z[2]);
|
||||
virtual ~UIntersectingCone();
|
||||
|
||||
int LineHitsCone(const UVector3& p, const UVector3& v, double& s1, double& s2);
|
||||
|
||||
bool HitOn(const double r, const double z);
|
||||
|
||||
inline double RLo() const
|
||||
{
|
||||
return rLo;
|
||||
}
|
||||
inline double RHi() const
|
||||
{
|
||||
return rHi;
|
||||
}
|
||||
inline double ZLo() const
|
||||
{
|
||||
return zLo;
|
||||
}
|
||||
inline double ZHi() const
|
||||
{
|
||||
return zHi;
|
||||
}
|
||||
|
||||
public: // without description
|
||||
|
||||
/*
|
||||
UIntersectingCone(__void__&);
|
||||
// Fake default constructor for usage restricted to direct object
|
||||
// persistency for clients requiring preallocation of memory for
|
||||
// persistifiable objects.
|
||||
*/
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
double zLo, zHi, // Z bounds of side
|
||||
rLo, rHi; // R bounds of side
|
||||
|
||||
bool type1; // True if cone is type 1
|
||||
// (std::fabs(z1-z2)>std::fabs(r1-r2))
|
||||
double A, B; // Cone radius parameter:
|
||||
// type 1: r = A + B*z
|
||||
// type 2: z = A + B*r
|
||||
|
||||
// int Solution (const UVector3 &p, const UVector3 &v, double a, double b, double c, double &s1, double &s2);
|
||||
|
||||
int LineHitsCone1(const UVector3& p, const UVector3& v,
|
||||
double& s1, double& s2);
|
||||
|
||||
int LineHitsCone1Optimized(const UVector3& p, const UVector3& v,
|
||||
double& s1, double& s2);
|
||||
|
||||
int LineHitsCone2(const UVector3& p, const UVector3& v,
|
||||
double& s1, double& s2);
|
||||
|
||||
// const double kInfinity;
|
||||
const static double EpsilonQuad;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,128 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UOrb
|
||||
//
|
||||
// Class description:
|
||||
//
|
||||
// A simple Orb defined by half-lengths on the three axis.
|
||||
// The center of the Orb matches the origin of the local reference frame.
|
||||
//
|
||||
// 19.10.12 Marek Gayer
|
||||
// Created from original implementation in Geant4
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#ifndef USOLIDS_UOrb
|
||||
#define USOLIDS_UOrb
|
||||
|
||||
#include "VUSolid.hh"
|
||||
#include "UUtils.hh"
|
||||
|
||||
class UOrb : public VUSolid
|
||||
{
|
||||
|
||||
public:
|
||||
UOrb() : VUSolid(), fR(0), fRTolerance(0) {}
|
||||
UOrb(const std::string& name, double pRmax);
|
||||
~UOrb() {}
|
||||
|
||||
UOrb(const UOrb& rhs);
|
||||
UOrb& operator=(const UOrb& rhs);
|
||||
|
||||
// Accessors
|
||||
inline double GetRadius() const;
|
||||
// Modifiers
|
||||
inline void SetRadius(double newRmax);
|
||||
|
||||
// Navigation methods
|
||||
EnumInside Inside(const UVector3& aPo6int) const;
|
||||
|
||||
double SafetyFromInside(const UVector3& aPoint,
|
||||
bool aAccurate = false) const;
|
||||
double SafetyFromOutside(const UVector3& aPoint,
|
||||
bool aAccurate = false) const;
|
||||
double DistanceToIn(const UVector3& aPoint,
|
||||
const UVector3& aDirection,
|
||||
double aPstep = UUtils::kInfinity) const;
|
||||
|
||||
double DistanceToOut(const UVector3& aPoint,
|
||||
const UVector3& aDirection,
|
||||
UVector3& aNormalVector,
|
||||
bool& aConvex,
|
||||
double aPstep = UUtils::kInfinity) const;
|
||||
|
||||
bool Normal(const UVector3& aPoint, UVector3& aNormal) const;
|
||||
void Extent(UVector3& aMin, UVector3& aMax) const;
|
||||
inline double Capacity();
|
||||
inline double SurfaceArea();
|
||||
UGeometryType GetEntityType() const;
|
||||
|
||||
void ComputeBBox(UBBox* /*aBox*/, bool /*aStore = false*/) {}
|
||||
|
||||
//G4Visualisation
|
||||
void GetParametersList(int /*aNumber*/, double* /*aArray*/) const;
|
||||
|
||||
VUSolid* Clone() const;
|
||||
|
||||
double GetRadialTolerance()
|
||||
{
|
||||
return fRTolerance;
|
||||
}
|
||||
|
||||
UVector3 GetPointOnSurface() const;
|
||||
|
||||
std::ostream& StreamInfo(std::ostream& os) const;
|
||||
|
||||
private:
|
||||
double fR;
|
||||
double fRTolerance;
|
||||
double fCubicVolume; // Cubic Volume
|
||||
double fSurfaceArea; // Surface Area
|
||||
|
||||
double DistanceToOutForOutsidePoints(const UVector3& p, const UVector3& v, UVector3& n) const;
|
||||
|
||||
};
|
||||
|
||||
inline double UOrb::GetRadius() const
|
||||
{
|
||||
return fR;
|
||||
}
|
||||
inline void UOrb::SetRadius(double newRmax)
|
||||
{
|
||||
fR = newRmax;
|
||||
}
|
||||
|
||||
inline double UOrb::Capacity()
|
||||
{
|
||||
if (fCubicVolume != 0.)
|
||||
{
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
fCubicVolume = (4 * UUtils::kPi / 3) * fR * fR * fR;
|
||||
}
|
||||
return fCubicVolume;
|
||||
}
|
||||
|
||||
inline double UOrb::SurfaceArea()
|
||||
{
|
||||
if (fSurfaceArea != 0.)
|
||||
{
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
fSurfaceArea = (4 * UUtils::kPi) * fR * fR;
|
||||
}
|
||||
return fSurfaceArea;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,221 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UPolyPhiFace
|
||||
//
|
||||
// Class description:
|
||||
//
|
||||
// Definition of a face that bounds a polycone or polyhedra when
|
||||
// it has a phi opening:
|
||||
//
|
||||
// UPolyPhiFace( const UReduciblePolygon *rz,
|
||||
// double phi,
|
||||
// double deltaPhi,
|
||||
// double phiOther )
|
||||
//
|
||||
// Specifically: a face that lies on a plane that passes through
|
||||
// the z axis. It has boundaries that are straight lines of arbitrary
|
||||
// length and direction, but with corners aways on the same side of
|
||||
// the z axis.
|
||||
//
|
||||
// 19.10.12 Marek Gayer
|
||||
// Created from original implementation in Geant4
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#ifndef UPolyPhiFace_hh
|
||||
#define UPolyPhiFace_hh
|
||||
|
||||
#include "UVCSGface.hh"
|
||||
#include "UVector2.hh"
|
||||
|
||||
class UReduciblePolygon;
|
||||
|
||||
struct UPolyPhiFaceVertex
|
||||
{
|
||||
double x, y, r, z; // position
|
||||
double rNorm,
|
||||
zNorm; // r/z normal
|
||||
UVector3 norm3D; // 3D normal
|
||||
|
||||
// Needed for Triangulation Algorithm
|
||||
//
|
||||
bool ear;
|
||||
UPolyPhiFaceVertex* next, *prev;
|
||||
};
|
||||
|
||||
struct UPolyPhiFaceEdge
|
||||
{
|
||||
UPolyPhiFaceEdge(): v0(0), v1(0), tr(.0), tz(0.), length(0.) {}
|
||||
UPolyPhiFaceVertex* v0, *v1; // Corners
|
||||
double tr, tz, // Unit vector along edge
|
||||
length; // Length of edge
|
||||
UVector3 norm3D; // 3D edge normal vector
|
||||
};
|
||||
|
||||
class UPolyPhiFace : public UVCSGface
|
||||
{
|
||||
|
||||
public: // with description
|
||||
|
||||
UPolyPhiFace(const UReduciblePolygon* rz,
|
||||
double phi, double deltaPhi, double phiOther);
|
||||
// Constructor.
|
||||
// Points r,z should be supplied in clockwise order in r,z.
|
||||
// For example:
|
||||
// [1]---------[2] ^ R
|
||||
// | | |
|
||||
// | | +--> z
|
||||
// [0]---------[3]
|
||||
|
||||
virtual ~UPolyPhiFace();
|
||||
// Destructor. Removes edges and corners.
|
||||
|
||||
UPolyPhiFace(const UPolyPhiFace& source);
|
||||
UPolyPhiFace& operator=(const UPolyPhiFace& source);
|
||||
// Copy constructor and assgnment operator.
|
||||
|
||||
bool Distance(const UVector3& p, const UVector3& v,
|
||||
bool outgoing, double surfTolerance,
|
||||
double& distance, double& distFromSurface,
|
||||
UVector3& normal, bool& allBehind);
|
||||
|
||||
double Safety(const UVector3& p, bool outgoing);
|
||||
|
||||
VUSolid::EnumInside Inside(const UVector3& p, double tolerance,
|
||||
double* bestDistance);
|
||||
|
||||
UVector3 Normal(const UVector3& p, double* bestDistance);
|
||||
|
||||
double Extent(const UVector3 axis);
|
||||
|
||||
/*
|
||||
void CalculateExtent( const EAxisType axis,
|
||||
const UVoxelLimits &voxelLimit,
|
||||
const UAffineTransform &tranform,
|
||||
USolidExtentList &extentList );
|
||||
*/
|
||||
|
||||
inline UVCSGface* Clone();
|
||||
// Allocates on the heap a clone of this face.
|
||||
|
||||
double SurfaceArea();
|
||||
double SurfaceTriangle(UVector3 p1, UVector3 p2,
|
||||
UVector3 p3, UVector3* p4);
|
||||
UVector3 GetPointOnFace();
|
||||
// Auxiliary methods for determination of points on surface.
|
||||
|
||||
public: // without description
|
||||
|
||||
UPolyPhiFace(__void__&);
|
||||
// Fake default constructor for usage restricted to direct object
|
||||
// persistency for clients requiring preallocation of memory for
|
||||
// persistifiable objects.
|
||||
|
||||
void Diagnose(VUSolid* solid);
|
||||
// Throw an exception if something is found inconsistent with
|
||||
// the solid. For debugging purposes only
|
||||
|
||||
protected:
|
||||
|
||||
bool InsideEdgesExact(double r, double z, double normSign,
|
||||
const UVector3& p, const UVector3& v);
|
||||
// Decide if the point in r,z is inside the edges of our face,
|
||||
// **but** do so consistently with other faces.
|
||||
|
||||
bool InsideEdges(double r, double z);
|
||||
bool InsideEdges(double r, double z, double* distRZ2,
|
||||
UPolyPhiFaceVertex** base3Dnorm = 0,
|
||||
UVector3** head3Dnorm = 0);
|
||||
// Decide if the point in r,z is inside the edges of our face.
|
||||
|
||||
inline double ExactZOrder(double z,
|
||||
double qx, double qy, double qz,
|
||||
const UVector3& v,
|
||||
double normSign,
|
||||
const UPolyPhiFaceVertex* vert) const;
|
||||
// Decide precisely whether a trajectory passes to the left, right,
|
||||
// or exactly passes through the z position of a vertex point in face.
|
||||
|
||||
void CopyStuff(const UPolyPhiFace& source);
|
||||
|
||||
protected:
|
||||
|
||||
// Functions used for Triangulation in Case of generic Polygone.
|
||||
// The triangulation is used for GetPointOnFace()
|
||||
|
||||
double Area2(UVector2 a, UVector2 b, UVector2 c);
|
||||
// Calculation of 2*Area of Triangle with Sign
|
||||
|
||||
bool Left(UVector2 a, UVector2 b, UVector2 c);
|
||||
bool LeftOn(UVector2 a, UVector2 b, UVector2 c);
|
||||
bool Collinear(UVector2 a, UVector2 b, UVector2 c);
|
||||
// Boolean functions for sign of Surface
|
||||
|
||||
bool IntersectProp(UVector2 a, UVector2 b,
|
||||
UVector2 c, UVector2 d);
|
||||
// Boolean function for finding proper intersection of two
|
||||
// line segments (a,b) and (c,d).
|
||||
|
||||
bool Between(UVector2 a, UVector2 b, UVector2 c);
|
||||
// Boolean function for determining if point c is between a and b
|
||||
// where the three points (a,b,c) are on the same line.
|
||||
|
||||
bool Intersect(UVector2 a, UVector2 b,
|
||||
UVector2 c, UVector2 d);
|
||||
// Boolean function for finding proper intersection or not
|
||||
// of two line segments (a,b) and (c,d).
|
||||
|
||||
bool Diagonalie(UPolyPhiFaceVertex* a, UPolyPhiFaceVertex* b);
|
||||
// Boolean Diagonalie help to determine if diagonal s
|
||||
// of segment (a,b) is convex or reflex.
|
||||
|
||||
bool InCone(UPolyPhiFaceVertex* a, UPolyPhiFaceVertex* b);
|
||||
// Boolean function for determining if b is inside the cone (a0,a,a1)
|
||||
// where a is the center of the cone.
|
||||
|
||||
bool Diagonal(UPolyPhiFaceVertex* a, UPolyPhiFaceVertex* b);
|
||||
// Boolean function for determining if Diagonal is possible
|
||||
// inside Polycone or PolyHedra.
|
||||
|
||||
void EarInit();
|
||||
// Initialisation for Triangulisation by ear tips.
|
||||
// For details see "Computational Geometry in C" by Joseph O'Rourke.
|
||||
|
||||
void Triangulate();
|
||||
// Triangularisation by ear tips for Polycone or Polyhedra.
|
||||
// For details see "Computational Geometry in C" by Joseph O'Rourke.
|
||||
// NOTE: a copy of the shape is made and this copy is reordered in
|
||||
// order to have a list of triangles. This list is used by the
|
||||
// method GetPointOnFace().
|
||||
|
||||
protected:
|
||||
|
||||
int numEdges; // Number of edges
|
||||
UPolyPhiFaceEdge* edges; // The edges of the face
|
||||
UPolyPhiFaceVertex* corners; // And the corners
|
||||
UVector3 normal; // Normal Unit vector
|
||||
UVector3 radial; // Unit vector along radial direction
|
||||
UVector3 surface; // Point on surface
|
||||
UVector3 surface_point; // Auxiliary point on surface used for
|
||||
// method GetPointOnFace()
|
||||
double rMin, rMax, // Extent in r
|
||||
zMin, zMax; // Extent in z
|
||||
bool allBehind; // True if the polycone/polyhedra
|
||||
// is behind the place of this face
|
||||
double fTolerance;// Surface thickness
|
||||
double fSurfaceArea; // Surface Area of PolyPhiFace
|
||||
UPolyPhiFaceVertex* triangles; // Auxiliary pointer to 'corners' used for
|
||||
// triangulation. Copy structure, changing
|
||||
// the structure of 'corners' (ear removal)
|
||||
};
|
||||
|
||||
#include "UPolyPhiFace.icc"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UPolyPhiFace.icc
|
||||
//
|
||||
// 19.10.12 Marek Gayer
|
||||
// Created from original implementation in Geant4
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
inline
|
||||
UVCSGface* UPolyPhiFace::Clone()
|
||||
{
|
||||
return new UPolyPhiFace(*this);
|
||||
}
|
||||
|
||||
// ExactZOrder
|
||||
//
|
||||
// Decide precisely whether a trajectory passes to the left, right, or exactly
|
||||
// passes through the z position of a vertex point in our face.
|
||||
//
|
||||
// Result is only determined within an arbitrary (positive) factor.
|
||||
// > 0 to the right
|
||||
// < 0 to the left
|
||||
// = 0 exactly on top of
|
||||
// In 99.9999% of the cases, a trivial calculation is used. In difficult
|
||||
// cases, a precise, compliant calculation is relied on.
|
||||
//
|
||||
inline
|
||||
double UPolyPhiFace::ExactZOrder(double z,
|
||||
double qx, double qy, double qz,
|
||||
const UVector3& v,
|
||||
double normSign,
|
||||
const UPolyPhiFaceVertex* vert) const
|
||||
{
|
||||
double answer = vert->z - z;
|
||||
if (std::fabs(answer) < VUSolid::Tolerance())
|
||||
{
|
||||
UVector3 qa(qx - vert->x + radial.x,
|
||||
qy - vert->y + radial.y, qz - vert->z),
|
||||
qb(qx - vert->x, qy - vert->y, qz - vert->z);
|
||||
UVector3 qacb = qa.Cross(qb);
|
||||
|
||||
answer = normSign * qacb.Dot(v) * (normal.y * radial.x - normal.x * radial.y);
|
||||
}
|
||||
|
||||
return answer;
|
||||
}
|
||||
@@ -0,0 +1,296 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UPolycone
|
||||
//
|
||||
// Class description:
|
||||
//
|
||||
// Class implementing a CSG-like type "PCON".
|
||||
//
|
||||
// UPolycone( const G4String& name,
|
||||
// G4double phiStart, // initial phi starting angle
|
||||
// G4double phiTotal, // total phi angle
|
||||
// G4int numZPlanes, // number of z planes
|
||||
// const G4double zPlane[], // position of z planes
|
||||
// const G4double rInner[], // tangent distance to inner surface
|
||||
// const G4double rOuter[]) // tangent distance to outer surface
|
||||
//
|
||||
// Alternative constructor, but limited to increasing-only Z sections:
|
||||
//
|
||||
// UPolycone( const G4String& name,
|
||||
// G4double phiStart, // initial phi starting angle
|
||||
// G4double phiTotal, // total phi angle
|
||||
// G4int numRZ, // number corners in r,z space
|
||||
// const G4double r[], // r coordinate of these corners
|
||||
// const G4double z[]) // z coordinate of these corners
|
||||
//
|
||||
// 19.04.13 Marek Gayer
|
||||
// Created from original implementation in Geant4
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#ifndef UPolycone_hh
|
||||
#define UPolycone_hh
|
||||
|
||||
#include "VUSolid.hh"
|
||||
|
||||
#include "UPolyconeSide.hh"
|
||||
#include "UVCSGfaceted.hh"
|
||||
#include "UVoxelizer.hh"
|
||||
|
||||
#include "UCons.hh"
|
||||
#include "UTubs.hh"
|
||||
|
||||
class UEnclosingCylinder;
|
||||
class UReduciblePolygon;
|
||||
class UPolyconeHistorical
|
||||
{
|
||||
public:
|
||||
UPolyconeHistorical();
|
||||
~UPolyconeHistorical();
|
||||
UPolyconeHistorical(const UPolyconeHistorical& source);
|
||||
UPolyconeHistorical& operator=(const UPolyconeHistorical& right);
|
||||
|
||||
double fStartAngle;
|
||||
double fOpeningAngle;
|
||||
int fNumZPlanes;
|
||||
std::vector<double> fZValues;
|
||||
std::vector<double> Rmin;
|
||||
std::vector<double> Rmax;
|
||||
};
|
||||
|
||||
class UPolycone : public VUSolid
|
||||
{
|
||||
|
||||
public: // with description
|
||||
|
||||
void Init(
|
||||
double phiStart, // initial phi starting angle
|
||||
double phiTotal, // total phi angle
|
||||
int numZPlanes, // number of z planes
|
||||
const double zPlane[], // position of z planes
|
||||
const double rInner[], // tangent distance to inner surface
|
||||
const double rOuter[]);
|
||||
|
||||
UPolycone(const std::string& name) : VUSolid(name)
|
||||
{
|
||||
}
|
||||
|
||||
UPolycone(const std::string& name,
|
||||
double phiStart, // initial phi starting angle
|
||||
double phiTotal, // total phi angle
|
||||
int numZPlanes, // number of z planes
|
||||
const double zPlane[], // position of z planes
|
||||
const double rInner[], // tangent distance to inner surface
|
||||
const double rOuter[]); // tangent distance to outer surface
|
||||
|
||||
|
||||
UPolycone(const std::string& name,
|
||||
double phiStart, // initial phi starting angle
|
||||
double phiTotal, // total phi angle
|
||||
int numRZ, // number corners in r,z space
|
||||
const double r[], // r coordinate of these corners
|
||||
const double z[]); // z coordinate of these corners
|
||||
|
||||
|
||||
virtual ~UPolycone();
|
||||
|
||||
void Reset();
|
||||
|
||||
// inline void SetOriginalParameters(UPolyconeHistorical* pars);
|
||||
|
||||
// inline void SetOriginalParameters();
|
||||
|
||||
std::ostream& StreamInfo(std::ostream& os) const;
|
||||
|
||||
VUSolid::EnumInside Inside(const UVector3& p) const;
|
||||
|
||||
double DistanceToIn(const UVector3& p, const UVector3& v, double aPstep = UUtils::kInfinity) const;
|
||||
|
||||
double SafetyFromInside(const UVector3& aPoint,
|
||||
bool aAccurate = false) const;
|
||||
double SafetyFromOutside(const UVector3& aPoint,
|
||||
bool aAccurate = false) const;
|
||||
|
||||
double DistanceToOut(const UVector3& aPoint,
|
||||
const UVector3& aDirection,
|
||||
UVector3& aNormalVector,
|
||||
bool& aConvex,
|
||||
double aPstep = UUtils::kInfinity) const;
|
||||
|
||||
bool Normal(const UVector3& aPoint, UVector3& aNormal) const;
|
||||
// virtual void Extent ( EAxisType aAxis, double &aMin, double &aMax ) const;
|
||||
void Extent(UVector3& aMin, UVector3& aMax) const;
|
||||
double Capacity();
|
||||
double SurfaceArea();
|
||||
UGeometryType GetEntityType() const;
|
||||
|
||||
void ComputeBBox(UBBox* /*aBox*/, bool /*aStore = false*/) {}
|
||||
|
||||
//G4Visualisation
|
||||
void GetParametersList(int /*aNumber*/, double* /*aArray*/) const {}
|
||||
VUSolid* Clone() const;
|
||||
|
||||
UPolycone(const UPolycone& source);
|
||||
UPolycone& operator=(const UPolycone& source);
|
||||
// Copy constructor and assignment operator.
|
||||
void CopyStuff(const UPolycone& source);
|
||||
UVector3 GetPointOnSurface() const;
|
||||
|
||||
// Methods for random point generation
|
||||
|
||||
UVector3 GetPointOnCone(double fRmin1, double fRmax1,
|
||||
double fRmin2, double fRmax2,
|
||||
double zOne, double zTwo,
|
||||
double& totArea) const;
|
||||
|
||||
UVector3 GetPointOnTubs(double fRMin, double fRMax,
|
||||
double zOne, double zTwo,
|
||||
double& totArea) const;
|
||||
|
||||
UVector3 GetPointOnCut(double fRMin1, double fRMax1,
|
||||
double fRMin2, double fRMax2,
|
||||
double zOne, double zTwo,
|
||||
double& totArea) const;
|
||||
|
||||
UVector3 GetPointOnRing(double fRMin, double fRMax,
|
||||
double fRMin2, double fRMax2,
|
||||
double zOne) const;
|
||||
|
||||
inline double GetStartPhi() const
|
||||
{
|
||||
return startPhi;
|
||||
}
|
||||
|
||||
inline double GetEndPhi() const
|
||||
{
|
||||
return endPhi;
|
||||
}
|
||||
|
||||
inline bool IsOpen() const
|
||||
{
|
||||
return phiIsOpen;
|
||||
}
|
||||
|
||||
inline bool IsGeneric() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
inline int GetNumRZCorner() const
|
||||
{
|
||||
return numCorner;
|
||||
}
|
||||
|
||||
inline UPolyconeSideRZ GetCorner(int index) const
|
||||
{
|
||||
return corners[index];
|
||||
}
|
||||
|
||||
inline UPolyconeHistorical* GetOriginalParameters() const
|
||||
{
|
||||
return fOriginalParameters;
|
||||
}
|
||||
|
||||
inline void SetOriginalParameters(UPolyconeHistorical* pars)
|
||||
{
|
||||
if (!pars)
|
||||
// UException("UPolycone3::SetOriginalParameters()", "GeomSolids0002",
|
||||
// FatalException, "NULL pointer to parameters!");
|
||||
*fOriginalParameters = *pars;
|
||||
}
|
||||
|
||||
protected: // without description
|
||||
|
||||
// int fNumSides;
|
||||
bool SetOriginalParameters(UReduciblePolygon* rz);
|
||||
// Here are our parameters
|
||||
|
||||
double startPhi; // Starting phi value (0 < phiStart < 2pi)
|
||||
double endPhi; // end phi value (0 < endPhi-phiStart < 2pi)
|
||||
bool phiIsOpen; // true if there is a phi segment
|
||||
int numCorner; // number RZ points
|
||||
UPolyconeSideRZ* corners; // corner r,z points
|
||||
UPolyconeHistorical* fOriginalParameters; // original input parameters
|
||||
double fCubicVolume; // Cubic Volume
|
||||
double fSurfaceArea; // Surface Area
|
||||
|
||||
inline void SetOriginalParameters()
|
||||
{
|
||||
int numPlanes = (int)numCorner / 2;
|
||||
|
||||
fOriginalParameters = new UPolyconeHistorical;
|
||||
|
||||
fOriginalParameters->fZValues.resize(numPlanes);
|
||||
fOriginalParameters->Rmin.resize(numPlanes);
|
||||
fOriginalParameters->Rmax.resize(numPlanes);
|
||||
|
||||
for (int j = 0; j < numPlanes; j++)
|
||||
{
|
||||
fOriginalParameters->fZValues[j] = corners[numPlanes + j].z;
|
||||
fOriginalParameters->Rmax[j] = corners[numPlanes + j].r;
|
||||
fOriginalParameters->Rmin[j] = corners[numPlanes - 1 - j].r;
|
||||
}
|
||||
|
||||
fOriginalParameters->fStartAngle = startPhi;
|
||||
fOriginalParameters->fOpeningAngle = endPhi - startPhi;
|
||||
fOriginalParameters->fNumZPlanes = numPlanes;
|
||||
}
|
||||
|
||||
UEnclosingCylinder* enclosingCylinder;
|
||||
|
||||
struct UPolyconeSection
|
||||
{
|
||||
VUSolid* solid;// true if all points in section are concave in regards to whole polycone, will be determined
|
||||
double shift;
|
||||
bool tubular;
|
||||
// double left, right;
|
||||
bool convex; // TURE if all points in section are concave in regards to whole polycone, will be determined, currently not implemented
|
||||
};
|
||||
|
||||
std::vector<double> fZs; // z coordinates of given sections
|
||||
std::vector<UPolyconeSection> fSections;
|
||||
int fMaxSection;
|
||||
|
||||
inline VUSolid::EnumInside InsideSection(int index, const UVector3& p) const;
|
||||
|
||||
inline double SafetyFromInsideSection(int index, const UVector3& p) const
|
||||
{
|
||||
const UPolyconeSection& section = fSections[index];
|
||||
UVector3 ps(p.x, p.y, p.z - section.shift);
|
||||
double res = section.solid->SafetyFromInside(ps, true);
|
||||
return res;
|
||||
}
|
||||
|
||||
inline double SafetyFromOutsideSection(int index, const UVector3& p) const
|
||||
{
|
||||
const UPolyconeSection& section = fSections[index];
|
||||
UVector3 ps(p.x, p.y, p.z - section.shift);
|
||||
double res = section.solid->SafetyFromOutside(ps, true);
|
||||
return res;
|
||||
}
|
||||
|
||||
bool NormalSection(int index, const UVector3& p, UVector3& n) const
|
||||
{
|
||||
const UPolyconeSection& section = fSections[index];
|
||||
UVector3 ps(p.x, p.y, p.z - section.shift);
|
||||
bool res = section.solid->Normal(ps, n);
|
||||
return res;
|
||||
}
|
||||
|
||||
inline int GetSection(double z) const
|
||||
{
|
||||
int section = UVoxelizer::BinarySearch(fZs, z);
|
||||
if (section < 0) section = 0;
|
||||
else if (section > fMaxSection) section = fMaxSection;
|
||||
return section;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,93 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UPolycone.icc
|
||||
//
|
||||
// Implementation of inline methods of UPolycone
|
||||
//
|
||||
// 19.04.13 Marek Gayer
|
||||
// Created from original implementation in Geant4
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
inline
|
||||
double UPolycone::GetStartPhi() const
|
||||
{
|
||||
return startPhi;
|
||||
}
|
||||
|
||||
inline
|
||||
double UPolycone::GetEndPhi() const
|
||||
{
|
||||
return endPhi;
|
||||
}
|
||||
|
||||
inline
|
||||
bool UPolycone::IsOpen() const
|
||||
{
|
||||
return phiIsOpen;
|
||||
}
|
||||
|
||||
inline
|
||||
bool UPolycone::IsGeneric() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
inline
|
||||
int UPolycone::GetNumRZCorner() const
|
||||
{
|
||||
return numCorner;
|
||||
}
|
||||
|
||||
inline
|
||||
UPolyconeSideRZ UPolycone::GetCorner(int index) const
|
||||
{
|
||||
return corners[index];
|
||||
}
|
||||
|
||||
inline
|
||||
UPolyconeHistorical* UPolycone::GetOriginalParameters() const
|
||||
{
|
||||
return fOriginalParameters;
|
||||
}
|
||||
|
||||
inline
|
||||
void UPolycone::SetOriginalParameters(UPolyconeHistorical* pars)
|
||||
{
|
||||
if (!pars)
|
||||
// UException("UPolycone::SetOriginalParameters()", "GeomSolids0002",
|
||||
// FatalException, "NULL pointer to parameters!");
|
||||
*fOriginalParameters = *pars;
|
||||
fCubicVolume = 0.;
|
||||
fpPolyhedron = 0;
|
||||
}
|
||||
|
||||
inline
|
||||
void UPolycone::SetOriginalParameters()
|
||||
{
|
||||
int numPlanes = (int)numCorner / 2;
|
||||
|
||||
fOriginalParameters = new UPolyconeHistorical;
|
||||
|
||||
fOriginalParameters->fZValues.resize(numPlanes);
|
||||
fOriginalParameters->Rmin.resize(numPlanes);
|
||||
fOriginalParameters->Rmax.resize(numPlanes);
|
||||
|
||||
for (int j = 0; j < numPlanes; j++)
|
||||
{
|
||||
fOriginalParameters->fZValues[j] = corners[numPlanes + j].z;
|
||||
fOriginalParameters->Rmax[j] = corners[numPlanes + j].r;
|
||||
fOriginalParameters->Rmin[j] = corners[numPlanes - 1 - j].r;
|
||||
}
|
||||
|
||||
fOriginalParameters->fStartAngle = startPhi;
|
||||
fOriginalParameters->fOpeningAngle = endPhi - startPhi;
|
||||
fOriginalParameters->fNumZPlanes = numPlanes;
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UPolyconeSide
|
||||
//
|
||||
// Class description:
|
||||
//
|
||||
// Class implmenting a face that represents one conical side
|
||||
// of a polycone:
|
||||
//
|
||||
// UPolyconeSide( const UPolyconeSideRZ *prevRZ,
|
||||
// const UPolyconeSideRZ *tail,
|
||||
// const UPolyconeSideRZ *head,
|
||||
// const UPolyconeSideRZ *nextRZ,
|
||||
// double phiStart, double deltaPhi,
|
||||
// bool phiIsOpen, bool isAllBehind=false )
|
||||
//
|
||||
// Values for r1,z1 and r2,z2 should be specified in clockwise
|
||||
// order in (r,z).
|
||||
//
|
||||
// 19.04.13 Marek Gayer
|
||||
// Created from original implementation in Geant4
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#ifndef UPolyconeSide_hh
|
||||
#define UPolyconeSide_hh
|
||||
|
||||
#include "UVCSGface.hh"
|
||||
|
||||
class UIntersectingCone;
|
||||
|
||||
struct UPolyconeSideRZ
|
||||
{
|
||||
double r, z; // start of vector
|
||||
};
|
||||
|
||||
class UPolyconeSidePrivateSubclass
|
||||
{
|
||||
public:
|
||||
std::pair<UVector3, double> fPhi; // Cached value for phi
|
||||
|
||||
void initialize()
|
||||
{
|
||||
fPhi.first = UVector3(0, 0, 0);
|
||||
fPhi.second = 0.0;
|
||||
};
|
||||
};
|
||||
|
||||
class UPolyconeSide : public UVCSGface
|
||||
{
|
||||
public:
|
||||
|
||||
UPolyconeSide(const UPolyconeSideRZ* prevRZ,
|
||||
const UPolyconeSideRZ* tail,
|
||||
const UPolyconeSideRZ* head,
|
||||
const UPolyconeSideRZ* nextRZ,
|
||||
double phiStart, double deltaPhi,
|
||||
bool phiIsOpen, bool isAllBehind = false);
|
||||
virtual ~UPolyconeSide();
|
||||
|
||||
UPolyconeSide(const UPolyconeSide& source);
|
||||
UPolyconeSide& operator=(const UPolyconeSide& source);
|
||||
|
||||
bool Distance(const UVector3& p, const UVector3& v,
|
||||
bool outgoing, double surfTolerance,
|
||||
double& distance, double& distFromSurface,
|
||||
UVector3& normal, bool& isAllBehind);
|
||||
|
||||
double Safety(const UVector3& p, bool outgoing);
|
||||
|
||||
VUSolid::EnumInside Inside(const UVector3& p, double tolerance,
|
||||
double* bestDistance);
|
||||
|
||||
UVector3 Normal(const UVector3& p, double* bestDistance);
|
||||
|
||||
double Extent(const UVector3 axis);
|
||||
|
||||
/*
|
||||
void CalculateExtent( const EAxisType axis,
|
||||
const UVoxelLimits &voxelLimit,
|
||||
const UAffineTransform &tranform,
|
||||
USolidExtentList &extentList );
|
||||
*/
|
||||
|
||||
UVCSGface* Clone()
|
||||
{
|
||||
return new UPolyconeSide(*this);
|
||||
}
|
||||
|
||||
double SurfaceArea();
|
||||
UVector3 GetPointOnFace();
|
||||
|
||||
public: // without description
|
||||
|
||||
UPolyconeSide(__void__&);
|
||||
// Fake default constructor for usage restricted to direct object
|
||||
// persistency for clients requiring preallocation of memory for
|
||||
// persistifiable objects.
|
||||
|
||||
protected:
|
||||
|
||||
double DistanceAway(const UVector3& p, bool opposite,
|
||||
double& distOutside2, double* rzNorm = 0);
|
||||
|
||||
bool PointOnCone(const UVector3& hit, double normSign,
|
||||
const UVector3& p,
|
||||
const UVector3& v, UVector3& normal);
|
||||
|
||||
void CopyStuff(const UPolyconeSide& source);
|
||||
|
||||
static void FindLineIntersect(double x1, double y1,
|
||||
double tx1, double ty1,
|
||||
double x2, double y2,
|
||||
double tx2, double ty2,
|
||||
double& x, double& y);
|
||||
|
||||
double GetPhi(const UVector3& p);
|
||||
|
||||
protected:
|
||||
|
||||
double r[2], z[2]; // r, z parameters, in specified order
|
||||
double startPhi, // Start phi (0 to 2pi), if phiIsOpen
|
||||
deltaPhi; // Delta phi (0 to 2pi), if phiIsOpen
|
||||
bool phiIsOpen; // True if there is a phi slice
|
||||
bool allBehind; // True if the entire solid is "behind" this face
|
||||
|
||||
UIntersectingCone* cone; // Our intersecting utility class
|
||||
|
||||
double rNorm, zNorm; // Normal to surface in r,z space
|
||||
double rS, zS; // Unit vector along surface in r,z space
|
||||
double length; // Length of face in r,z space
|
||||
double prevRS,
|
||||
prevZS; // Unit vector along previous polyconeSide
|
||||
double nextRS,
|
||||
nextZS; // Unit vector along next polyconeSide
|
||||
|
||||
double rNormEdge[2],
|
||||
zNormEdge[2]; // Normal to edges
|
||||
|
||||
int ncorners;
|
||||
UVector3* corners; // The coordinates of the corners (if phiIsOpen)
|
||||
|
||||
private:
|
||||
double tolerance; // Geometrical surface thickness
|
||||
double fSurfaceArea; // Used for surface calculation
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,194 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UPolyhedra
|
||||
//
|
||||
// Class description:
|
||||
//
|
||||
// Class implementing a CSG-like type "PGON":
|
||||
//
|
||||
// UPolyhedra( const std::string& name,
|
||||
// double phiStart, - initial phi starting angle
|
||||
// double phiTotal, - total phi angle
|
||||
// int numSide, - number sides
|
||||
// int numZPlanes, - number of z planes
|
||||
// const double zPlane[], - position of z planes
|
||||
// const double rInner[], - tangent distance to inner surface
|
||||
// const double rOuter[] ) - tangent distance to outer surface
|
||||
//
|
||||
// UPolyhedra( const std::string& name,
|
||||
// double phiStart, - initial phi starting angle
|
||||
// double phiTotal, - total phi angle
|
||||
// int numSide, - number sides
|
||||
// int numRZ, - number corners in r,z space
|
||||
// const double r[], - r coordinate of these corners
|
||||
// const double z[] ) - z coordinate of these corners
|
||||
//
|
||||
// 19.09.13 Marek Gayer
|
||||
// Created from original implementation in Geant4
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#ifndef UPolyhedra_hh
|
||||
#define UPolyhedra_hh
|
||||
|
||||
#include "UVCSGfaceted.hh"
|
||||
#include "UPolyhedraSide.hh"
|
||||
|
||||
class UEnclosingCylinder;
|
||||
class UReduciblePolygon;
|
||||
class UPolyhedraHistorical
|
||||
{
|
||||
public:
|
||||
|
||||
UPolyhedraHistorical();
|
||||
~UPolyhedraHistorical();
|
||||
UPolyhedraHistorical(const UPolyhedraHistorical& source);
|
||||
UPolyhedraHistorical& operator=(const UPolyhedraHistorical& right);
|
||||
|
||||
double fStartAngle;
|
||||
double fOpeningAngle;
|
||||
int fNumSide;
|
||||
int fNumZPlanes;
|
||||
std::vector<double> fZValues;
|
||||
std::vector<double> Rmin;
|
||||
std::vector<double> Rmax;
|
||||
};
|
||||
|
||||
class UPolyhedra : public UVCSGfaceted
|
||||
{
|
||||
protected:
|
||||
|
||||
inline UPolyhedra(const std::string& name) : UVCSGfaceted(name) {}
|
||||
|
||||
public: // with description
|
||||
|
||||
void Init(
|
||||
double phiStart, // initial phi starting angle
|
||||
double phiTotal, // total phi angle
|
||||
int numSide, // number sides
|
||||
int numZPlanes, // number of z planes
|
||||
const double zPlane[], // position of z planes
|
||||
const double rInner[], // tangent distance to inner surface
|
||||
const double rOuter[]); // tangent distance to outer surface
|
||||
|
||||
UPolyhedra(const std::string& name,
|
||||
double phiStart, // initial phi starting angle
|
||||
double phiTotal, // total phi angle
|
||||
int numSide, // number sides
|
||||
int numZPlanes, // number of z planes
|
||||
const double zPlane[], // position of z planes
|
||||
const double rInner[], // tangent distance to inner surface
|
||||
const double rOuter[]); // tangent distance to outer surface
|
||||
|
||||
UPolyhedra(const std::string& name,
|
||||
double phiStart, // initial phi starting angle
|
||||
double phiTotal, // total phi angle
|
||||
int numSide, // number sides
|
||||
int numRZ, // number corners in r,z space
|
||||
const double r[], // r coordinate of these corners
|
||||
const double z[]); // z coordinate of these corners
|
||||
|
||||
virtual ~UPolyhedra();
|
||||
|
||||
// Methods for solid
|
||||
|
||||
void GetParametersList(int /*aNumber*/, double* /*aArray*/) const {}
|
||||
|
||||
void ComputeBBox(UBBox* /*aBox*/, bool /*aStore*/)
|
||||
{
|
||||
// Computes bounding box.
|
||||
std::cout << "ComputeBBox - Not implemented" << std::endl;
|
||||
}
|
||||
|
||||
VUSolid::EnumInside Inside(const UVector3& p) const;
|
||||
|
||||
// double DistanceToInDelete( const UVector3 &p,
|
||||
// const UVector3 &v ) const;
|
||||
|
||||
double SafetyFromOutside(const UVector3& aPoint, bool aAccurate = false) const;
|
||||
|
||||
UGeometryType GetEntityType() const;
|
||||
|
||||
VUSolid* Clone() const;
|
||||
|
||||
UVector3 GetPointOnSurface() const;
|
||||
|
||||
std::ostream& StreamInfo(std::ostream& os) const;
|
||||
|
||||
bool Reset();
|
||||
|
||||
// Accessors
|
||||
|
||||
inline int GetNumSide() const;
|
||||
inline double GetStartPhi() const;
|
||||
inline double GetEndPhi() const;
|
||||
inline bool IsOpen() const;
|
||||
inline bool IsGeneric() const;
|
||||
inline int GetNumRZCorner() const;
|
||||
inline UPolyhedraSideRZ GetCorner(const int index) const;
|
||||
|
||||
inline UPolyhedraHistorical* GetOriginalParameters();
|
||||
// Returns internal scaled parameters.
|
||||
inline void SetOriginalParameters(UPolyhedraHistorical& pars);
|
||||
// Sets internal parameters. Parameters 'Rmin' and 'Rmax' in input must
|
||||
// be scaled first by a factor computed as 'cos(0.5*phiTotal/theNumSide)',
|
||||
// if not already scaled.
|
||||
|
||||
public: // without description
|
||||
|
||||
double DistanceToIn(const UVector3& p,
|
||||
const UVector3& v, double aPstep = UUtils::kInfinity) const;
|
||||
|
||||
UPolyhedra(const UPolyhedra& source);
|
||||
UPolyhedra& operator=(const UPolyhedra& source);
|
||||
// Copy constructor and assignment operator.
|
||||
|
||||
protected: // without description
|
||||
|
||||
inline void SetOriginalParameters();
|
||||
// Sets internal parameters for the generic constructor.
|
||||
|
||||
void Create(double phiStart, // initial phi starting angle
|
||||
double phiTotal, // total phi angle
|
||||
int numSide, // number sides
|
||||
UReduciblePolygon* rz); // rz coordinates
|
||||
// Generates the shape and is called by each constructor, after the
|
||||
// conversion of the arguments
|
||||
|
||||
void CopyStuff(const UPolyhedra& source);
|
||||
void DeleteStuff();
|
||||
|
||||
// Methods for generation of random points on surface
|
||||
|
||||
UVector3 GetPointOnPlane(UVector3 p0, UVector3 p1,
|
||||
UVector3 p2, UVector3 p3) const;
|
||||
UVector3 GetPointOnTriangle(UVector3 p0, UVector3 p1,
|
||||
UVector3 p2) const;
|
||||
UVector3 GetPointOnSurfaceCorners() const;
|
||||
|
||||
void Extent(UVector3& aMin, UVector3& aMax) const;
|
||||
|
||||
protected: // without description
|
||||
|
||||
int fNumSides; // Number of sides
|
||||
double fStartPhi; // Starting phi value (0 < phiStart < 2pi)
|
||||
double fEndPhi; // end phi value (0 < endPhi-phiStart < 2pi)
|
||||
bool fPhiIsOpen; // true if there is a phi segment
|
||||
bool fGenericPgon; // true if created through the 2nd generic constructor
|
||||
int fNumCorner; // number RZ points
|
||||
UPolyhedraSideRZ* fCorners; // our corners
|
||||
UPolyhedraHistorical fOriginalParameters; // original input parameters
|
||||
UEnclosingCylinder* fEnclosingCylinder;
|
||||
|
||||
};
|
||||
|
||||
#include "UPolyhedra.icc"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,95 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UPolyhedra.icc
|
||||
//
|
||||
// Implementation of inline methods of UPolyhedra
|
||||
//
|
||||
// 19.09.13 Marek Gayer
|
||||
// Created from original implementation in Geant4
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
inline
|
||||
int UPolyhedra::GetNumSide() const
|
||||
{
|
||||
return fNumSides;
|
||||
}
|
||||
|
||||
inline
|
||||
double UPolyhedra::GetStartPhi() const
|
||||
{
|
||||
return fStartPhi;
|
||||
}
|
||||
|
||||
inline
|
||||
double UPolyhedra::GetEndPhi() const
|
||||
{
|
||||
return fEndPhi;
|
||||
}
|
||||
|
||||
inline
|
||||
bool UPolyhedra::IsOpen() const
|
||||
{
|
||||
return fPhiIsOpen;
|
||||
}
|
||||
|
||||
inline
|
||||
bool UPolyhedra::IsGeneric() const
|
||||
{
|
||||
return fGenericPgon;
|
||||
}
|
||||
|
||||
inline
|
||||
int UPolyhedra::GetNumRZCorner() const
|
||||
{
|
||||
return fNumCorner;
|
||||
}
|
||||
|
||||
inline
|
||||
UPolyhedraSideRZ UPolyhedra::GetCorner(const int index) const
|
||||
{
|
||||
return fCorners[index];
|
||||
}
|
||||
|
||||
inline
|
||||
UPolyhedraHistorical* UPolyhedra::GetOriginalParameters()
|
||||
{
|
||||
return &fOriginalParameters;
|
||||
}
|
||||
|
||||
inline
|
||||
void UPolyhedra::SetOriginalParameters(UPolyhedraHistorical& pars)
|
||||
{
|
||||
fOriginalParameters = pars;
|
||||
fCubicVolume = 0.;
|
||||
}
|
||||
|
||||
inline
|
||||
void UPolyhedra::SetOriginalParameters()
|
||||
{
|
||||
int fNumPlanes = (int) fNumCorner / 2;
|
||||
|
||||
fOriginalParameters.fZValues.resize(fNumPlanes);
|
||||
fOriginalParameters.Rmin.resize(fNumPlanes);
|
||||
fOriginalParameters.Rmax.resize(fNumPlanes);
|
||||
|
||||
for (int j = 0; j < fNumPlanes; j++)
|
||||
{
|
||||
fOriginalParameters.fZValues[j] = fCorners[fNumPlanes + j].z;
|
||||
fOriginalParameters.Rmax[j] = fCorners[fNumPlanes + j].r;
|
||||
fOriginalParameters.Rmin[j] = fCorners[fNumPlanes - 1 - j].r;
|
||||
}
|
||||
|
||||
fOriginalParameters.fStartAngle = fStartPhi;
|
||||
fOriginalParameters.fOpeningAngle = fEndPhi - fStartPhi;
|
||||
fOriginalParameters.fNumZPlanes = fNumPlanes;
|
||||
fOriginalParameters.fNumSide = fNumSides;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UPolyhedraSide
|
||||
//
|
||||
// Class description:
|
||||
//
|
||||
// Class implementing a face that represents one segmented side
|
||||
// of a polyhedra:
|
||||
//
|
||||
// UPolyhedraSide( const UPolyhedraSideRZ *prevRZ,
|
||||
// const UPolyhedraSideRZ *tail,
|
||||
// const UPolyhedraSideRZ *head,
|
||||
// const UPolyhedraSideRZ *nextRZ,
|
||||
// int numSide,
|
||||
// double phiStart, double phiTotal,
|
||||
// bool phiIsOpen, bool isAllBehind=false )
|
||||
//
|
||||
// Values for r1,z1 and r2,z2 should be specified in clockwise
|
||||
// order in (r,z).
|
||||
//
|
||||
// 19.09.13 Marek Gayer
|
||||
// Created from original implementation in Geant4
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#ifndef UPolyhedraSide_hh
|
||||
#define UPolyhedraSide_hh
|
||||
|
||||
#include "UVCSGface.hh"
|
||||
|
||||
class UIntersectingCone;
|
||||
|
||||
struct UPolyhedraSideRZ
|
||||
{
|
||||
double r, z; // start of vector
|
||||
};
|
||||
|
||||
class UPolyhedraSide : public UVCSGface
|
||||
{
|
||||
|
||||
public: // with description
|
||||
|
||||
UPolyhedraSide(const UPolyhedraSideRZ* prevRZ,
|
||||
const UPolyhedraSideRZ* tail,
|
||||
const UPolyhedraSideRZ* head,
|
||||
const UPolyhedraSideRZ* nextRZ,
|
||||
int numSide,
|
||||
double phiStart, double phiTotal,
|
||||
bool phiIsOpen, bool isAllBehind = false);
|
||||
virtual ~UPolyhedraSide();
|
||||
|
||||
UPolyhedraSide(const UPolyhedraSide& source);
|
||||
UPolyhedraSide& operator=(const UPolyhedraSide& source);
|
||||
|
||||
bool Distance(const UVector3& p, const UVector3& v,
|
||||
bool outgoing, double surfTolerance,
|
||||
double& distance, double& distFromSurface,
|
||||
UVector3& normal, bool& allBehind);
|
||||
|
||||
double Safety(const UVector3& p, bool outgoing);
|
||||
|
||||
VUSolid::EnumInside Inside(const UVector3& p, double tolerance,
|
||||
double* bestDistance);
|
||||
|
||||
UVector3 Normal(const UVector3& p, double* bestDistance);
|
||||
|
||||
double Extent(const UVector3 axis);
|
||||
|
||||
UVCSGface* Clone()
|
||||
{
|
||||
return new UPolyhedraSide(*this);
|
||||
}
|
||||
|
||||
public: // without description
|
||||
|
||||
// Methods used for GetPointOnSurface()
|
||||
|
||||
double SurfaceTriangle(UVector3 p1,
|
||||
UVector3 p2,
|
||||
UVector3 p3,
|
||||
UVector3* p4);
|
||||
UVector3 GetPointOnPlane(UVector3 p0, UVector3 p1,
|
||||
UVector3 p2, UVector3 p3,
|
||||
double* Area);
|
||||
double SurfaceArea();
|
||||
UVector3 GetPointOnFace();
|
||||
|
||||
public: // without description
|
||||
|
||||
UPolyhedraSide(__void__&);
|
||||
// Fake default constructor for usage restricted to direct object
|
||||
// persistency for clients requiring preallocation of memory for
|
||||
// persistifiable objects.
|
||||
|
||||
protected:
|
||||
|
||||
//
|
||||
// A couple internal data structures
|
||||
//
|
||||
struct sUPolyhedraSideVec; // Secret recipe for allowing
|
||||
friend struct sUPolyhedraSideVec; // protected nested structures
|
||||
|
||||
typedef struct sUPolyhedraSideEdge
|
||||
{
|
||||
UVector3 normal; // Unit normal to this edge
|
||||
UVector3 corner[2]; // The two corners of this phi edge
|
||||
UVector3 cornNorm[2]; // The normals of these corners
|
||||
} UPolyhedraSideEdge;
|
||||
|
||||
typedef struct sUPolyhedraSideVec
|
||||
{
|
||||
UVector3 normal, // Normal (point out of the shape)
|
||||
center, // Point in center of side
|
||||
surfPhi, // Unit vector on surface pointing along phi
|
||||
surfRZ; // Unit vector on surface pointing along R/Z
|
||||
UPolyhedraSideEdge* edges[2]; // The phi boundary edges to this side
|
||||
// [0]=low phi [1]=high phi
|
||||
UVector3 edgeNorm[2]; // RZ edge normals [i] at {r[i],z[i]}
|
||||
} UPolyhedraSideVec;
|
||||
|
||||
bool IntersectSidePlane(const UVector3& p, const UVector3& v,
|
||||
const UPolyhedraSideVec& vec,
|
||||
double normSign,
|
||||
double surfTolerance,
|
||||
double& distance,
|
||||
double& distFromSurface);
|
||||
|
||||
int LineHitsSegments(const UVector3& p,
|
||||
const UVector3& v,
|
||||
int* i1, int* i2);
|
||||
|
||||
int ClosestPhiSegment(double phi);
|
||||
|
||||
int PhiSegment(double phi);
|
||||
|
||||
double GetPhi(const UVector3& p);
|
||||
|
||||
double DistanceToOneSide(const UVector3& p,
|
||||
const UPolyhedraSideVec& vec,
|
||||
double* normDist);
|
||||
|
||||
double DistanceAway(const UVector3& p,
|
||||
const UPolyhedraSideVec& vec,
|
||||
double* normDist);
|
||||
|
||||
void CopyStuff(const UPolyhedraSide& source);
|
||||
|
||||
protected:
|
||||
|
||||
int numSide; // Number sides
|
||||
double r[2], z[2]; // r, z parameters, in specified order
|
||||
double startPhi, // Start phi (0 to 2pi), if phiIsOpen
|
||||
deltaPhi, // Delta phi (0 to 2pi), if phiIsOpen
|
||||
endPhi; // End phi (>startPhi), if phiIsOpen
|
||||
bool phiIsOpen; // True if there is a phi slice
|
||||
bool allBehind; // True if the entire solid is "behind" this face
|
||||
|
||||
UIntersectingCone* cone; // Our intersecting cone
|
||||
|
||||
UPolyhedraSideVec* vecs; // Vector Set for each facet of our face
|
||||
UPolyhedraSideEdge* edges; // The edges belong to vecs
|
||||
double lenRZ, // RZ length of each side
|
||||
lenPhi[2]; // Phi dimensions of each side
|
||||
double edgeNorm; // Normal in RZ/Phi space to each side
|
||||
|
||||
private:
|
||||
|
||||
std::pair<UVector3, double> fPhi; // Cached value for phi
|
||||
double kCarTolerance; // Geometrical surface thickness
|
||||
double fSurfaceArea; // Surface Area
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,190 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UReduciblePolygon
|
||||
//
|
||||
// Class description:
|
||||
//
|
||||
// Utility class used to specify, test, reduce, and/or otherwise
|
||||
// manipulate a 2D polygon.
|
||||
//
|
||||
// For this class, a polygon consists of n > 2 points in 2D
|
||||
// space (a,b). The polygon is always closed by connecting the
|
||||
// last point to the first. A UReduciblePolygon is guaranteed
|
||||
// to fulfill this definition in all instances.
|
||||
//
|
||||
// Illegal manipulations (such that a valid polygon would be
|
||||
// produced) result in an error return if possible and
|
||||
// otherwise a // UException.
|
||||
//
|
||||
// The Set of manipulations is limited currently to what
|
||||
// is needed for UPolycone and UPolyhedra.
|
||||
//
|
||||
// 19.09.13 Marek Gayer
|
||||
// Created from original implementation in Geant4
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#ifndef UReduciblePolygon_hh
|
||||
#define UReduciblePolygon_hh
|
||||
|
||||
#include "UTypes.hh"
|
||||
|
||||
class UReduciblePolygon
|
||||
{
|
||||
friend class UReduciblePolygonIterator;
|
||||
|
||||
public:
|
||||
//
|
||||
// Creator: via simple a/b arrays
|
||||
//
|
||||
UReduciblePolygon(const double a[], const double b[], int n);
|
||||
|
||||
//
|
||||
// Creator: a special version for UPolygon and UPolycone
|
||||
// that takes two a points at planes of b
|
||||
// (where a==r and b==z for the GEANT3 classic PCON and PGON)
|
||||
//
|
||||
UReduciblePolygon(const double rmin[], const double rmax[],
|
||||
const double z[], int n);
|
||||
|
||||
virtual ~UReduciblePolygon();
|
||||
|
||||
//
|
||||
// Queries
|
||||
//
|
||||
inline int NumVertices() const
|
||||
{
|
||||
return numVertices;
|
||||
}
|
||||
|
||||
inline double Amin() const
|
||||
{
|
||||
return aMin;
|
||||
}
|
||||
inline double Amax() const
|
||||
{
|
||||
return aMax;
|
||||
}
|
||||
inline double Bmin() const
|
||||
{
|
||||
return bMin;
|
||||
}
|
||||
inline double Bmax() const
|
||||
{
|
||||
return bMax;
|
||||
}
|
||||
|
||||
void CopyVertices(double a[], double b[]) const;
|
||||
|
||||
//
|
||||
// Manipulations
|
||||
//
|
||||
void ScaleA(double scale);
|
||||
void ScaleB(double scale);
|
||||
|
||||
bool RemoveDuplicateVertices(double tolerance);
|
||||
bool RemoveRedundantVertices(double tolerance);
|
||||
|
||||
void ReverseOrder();
|
||||
void StartWithZMin();
|
||||
//
|
||||
// Tests
|
||||
//
|
||||
double Area();
|
||||
bool CrossesItself(double tolerance);
|
||||
bool BisectedBy(double a1, double b1,
|
||||
double a2, double b2, double tolerance);
|
||||
|
||||
void Print(); // Debugging only
|
||||
|
||||
public: // without description
|
||||
|
||||
protected:
|
||||
|
||||
void Create(const double a[], const double b[], int n);
|
||||
|
||||
void CalculateMaxMin();
|
||||
|
||||
//
|
||||
// Below are member values that are *always* kept up to date (please!)
|
||||
//
|
||||
double aMin, aMax, bMin, bMax;
|
||||
int numVertices;
|
||||
|
||||
//
|
||||
// A subclass which holds the vertices in a single-linked list
|
||||
//
|
||||
// Yeah, call me an old-fashioned c hacker, but I cannot make
|
||||
// myself use the rogue tools for this trivial list.
|
||||
//
|
||||
struct ABVertex; // Secret recipe for allowing
|
||||
friend struct ABVertex; // protected nested structures
|
||||
struct ABVertex
|
||||
{
|
||||
ABVertex() : a(0.), b(0.), next(0) {}
|
||||
double a, b;
|
||||
ABVertex* next;
|
||||
};
|
||||
|
||||
ABVertex* vertexHead;
|
||||
|
||||
private:
|
||||
|
||||
UReduciblePolygon(const UReduciblePolygon&);
|
||||
UReduciblePolygon& operator=(const UReduciblePolygon&);
|
||||
// Private copy constructor and assignment operator.
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// A companion class for iterating over the vertices of our polygon.
|
||||
// It is simple enough that all routines are declared inline here.
|
||||
//
|
||||
class UReduciblePolygonIterator
|
||||
{
|
||||
public:
|
||||
|
||||
UReduciblePolygonIterator(const UReduciblePolygon* theSubject)
|
||||
{
|
||||
subject = theSubject;
|
||||
current = 0;
|
||||
}
|
||||
|
||||
void Begin()
|
||||
{
|
||||
current = subject->vertexHead;
|
||||
}
|
||||
bool Next()
|
||||
{
|
||||
if (current) current = current->next;
|
||||
return Valid();
|
||||
}
|
||||
|
||||
bool Valid() const
|
||||
{
|
||||
return current != 0;
|
||||
}
|
||||
|
||||
double GetA() const
|
||||
{
|
||||
return current->a;
|
||||
}
|
||||
double GetB() const
|
||||
{
|
||||
return current->b;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
const UReduciblePolygon* subject; // Who are we iterating over
|
||||
UReduciblePolygon::ABVertex* current; // Current vertex
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,503 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// USphere
|
||||
//
|
||||
// Class description:
|
||||
//
|
||||
// A USphere is, in the general case, a section of a spherical shell,
|
||||
// between specified phi and theta angles
|
||||
//
|
||||
// The phi and theta segments are described by a starting angle,
|
||||
// and the +ve delta angle for the shape.
|
||||
// If the delta angle is >=2*UUtils::kPi, or >=UUtils::kPi the shape is treated as
|
||||
// continuous in phi or theta respectively.
|
||||
//
|
||||
// Theta must lie between 0-UUtils::kPi (incl).
|
||||
//
|
||||
// Member Data:
|
||||
//
|
||||
// fRmin inner radius
|
||||
// fRmax outer radius
|
||||
//
|
||||
// fSPhi starting angle of the segment in radians
|
||||
// fDPhi delta angle of the segment in radians
|
||||
//
|
||||
// fSTheta starting angle of the segment in radians
|
||||
// fDTheta delta angle of the segment in radians
|
||||
//
|
||||
//
|
||||
// Note:
|
||||
// Internally fSPhi & fDPhi are adjusted so that fDPhi<=2PI,
|
||||
// and fDPhi+fSPhi<=2PI. This enables simpler comparisons to be
|
||||
// made with (say) Phi of a point.
|
||||
//
|
||||
// 19.10.12 Marek Gayer
|
||||
// Created from original implementation in Geant4
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#ifndef USphere_HH
|
||||
#define USphere_HH
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "VUSolid.hh"
|
||||
|
||||
class UVisExtent;
|
||||
|
||||
class USphere : public VUSolid
|
||||
{
|
||||
public: // with description
|
||||
|
||||
USphere(const std::string& pName,
|
||||
double pRmin, double pRmax,
|
||||
double pSPhi, double pDPhi,
|
||||
double pSTheta, double pDTheta);
|
||||
//
|
||||
// Constructs a sphere or sphere shell section
|
||||
// with the given name and dimensions
|
||||
|
||||
~USphere();
|
||||
//
|
||||
// Destructor
|
||||
|
||||
// Accessors
|
||||
|
||||
inline double GetInnerRadius() const;
|
||||
inline double GetOuterRadius() const;
|
||||
inline double GetStartPhiAngle() const;
|
||||
inline double GetDeltaPhiAngle() const;
|
||||
inline double GetStartThetaAngle() const;
|
||||
inline double GetDeltaThetaAngle() const;
|
||||
|
||||
// Modifiers
|
||||
|
||||
inline void SetInnerRadius(double newRMin);
|
||||
inline void SetOuterRadius(double newRmax);
|
||||
inline void SetStartPhiAngle(double newSphi, bool trig = true);
|
||||
inline void SetDeltaPhiAngle(double newDphi);
|
||||
inline void SetStartThetaAngle(double newSTheta);
|
||||
inline void SetDeltaThetaAngle(double newDTheta);
|
||||
|
||||
// Methods for solid
|
||||
|
||||
inline double Capacity();
|
||||
double SurfaceArea();
|
||||
|
||||
|
||||
VUSolid::EnumInside Inside(const UVector3& p) const;
|
||||
|
||||
bool Normal(const UVector3& p, UVector3& n) const;
|
||||
|
||||
double DistanceToIn(const UVector3& p, const UVector3& v, double aPstep = UUtils::kInfinity) const;
|
||||
|
||||
double SafetyFromOutside(const UVector3& p, bool aAccurate = false) const;
|
||||
|
||||
double DistanceToOut(const UVector3& p, const UVector3& v, UVector3& n, bool& validNorm, double aPstep = UUtils::kInfinity) const;
|
||||
|
||||
|
||||
double SafetyFromInside(const UVector3& p, bool aAccurate = false) const;
|
||||
|
||||
UGeometryType GetEntityType() const;
|
||||
|
||||
UVector3 GetPointOnSurface() const;
|
||||
|
||||
VUSolid* Clone() const;
|
||||
|
||||
std::ostream& StreamInfo(std::ostream& os) const;
|
||||
|
||||
// Visualisation functions
|
||||
|
||||
UVisExtent GetExtent() const;
|
||||
|
||||
|
||||
|
||||
public: // without description
|
||||
|
||||
void Extent(UVector3& aMin, UVector3& aMax) const;
|
||||
|
||||
void GetParametersList(int /*aNumber*/, double* /*aArray*/) const;
|
||||
|
||||
|
||||
virtual void ComputeBBox(UBBox* /*aBox*/, bool /*aStore = false*/) {}
|
||||
|
||||
USphere(const USphere& rhs);
|
||||
USphere& operator=(const USphere& rhs);
|
||||
// Copy constructor and assignment operator.
|
||||
|
||||
// Old access functions
|
||||
|
||||
inline double GetRmin() const;
|
||||
inline double GetRmax() const;
|
||||
inline double GetSPhi() const;
|
||||
inline double GetDPhi() const;
|
||||
inline double GetSTheta() const;
|
||||
inline double GetDTheta() const;
|
||||
inline double GetInsideRadius() const;
|
||||
inline void SetInsideRadius(double newRmin);
|
||||
|
||||
private:
|
||||
|
||||
double fCubicVolume;
|
||||
double fSurfaceArea;
|
||||
inline void Initialize();
|
||||
//
|
||||
// Reset relevant values to zero
|
||||
|
||||
inline void CheckThetaAngles(double sTheta, double dTheta);
|
||||
inline void CheckSPhiAngle(double sPhi);
|
||||
inline void CheckDPhiAngle(double dPhi);
|
||||
inline void CheckPhiAngles(double sPhi, double dPhi);
|
||||
//
|
||||
// Reset relevant flags and angle values
|
||||
|
||||
inline void InitializePhiTrigonometry();
|
||||
inline void InitializeThetaTrigonometry();
|
||||
//
|
||||
// Recompute relevant trigonometric values and cache them
|
||||
|
||||
UVector3 ApproxSurfaceNormal(const UVector3& p) const;
|
||||
//
|
||||
// Algorithm for SurfaceNormal() following the original
|
||||
// specification for points not on the surface
|
||||
|
||||
private:
|
||||
|
||||
// Used by distanceToOut
|
||||
//
|
||||
enum ESide {kNull, kRMin, kRMax, kSPhi, kEPhi, kSTheta, kETheta};
|
||||
|
||||
// used by normal
|
||||
//
|
||||
enum ENorm {kNRMin, kNRMax, kNSPhi, kNEPhi, kNSTheta, kNETheta};
|
||||
|
||||
double fRminTolerance, kTolerance, kAngTolerance,
|
||||
kRadTolerance, fEpsilon;
|
||||
//
|
||||
// Radial and angular tolerances
|
||||
|
||||
double fRmin, fRmax, fSPhi, fDPhi, fSTheta, fDTheta;
|
||||
//
|
||||
// Radial and angular dimensions
|
||||
|
||||
double sinCPhi, cosCPhi, cosHDPhiOT, cosHDPhiIT,
|
||||
sinSPhi, cosSPhi, sinEPhi, cosEPhi, hDPhi, cPhi, ePhi;
|
||||
//
|
||||
// Cached trigonometric values for Phi angle
|
||||
|
||||
double sinSTheta, cosSTheta, sinETheta, cosETheta,
|
||||
tanSTheta, tanSTheta2, tanETheta, tanETheta2, eTheta;
|
||||
//
|
||||
// Cached trigonometric values for Theta angle
|
||||
|
||||
bool fFullPhiSphere, fFullThetaSphere, fFullSphere;
|
||||
//
|
||||
// Flags for identification of section, shell or full sphere
|
||||
};
|
||||
|
||||
inline
|
||||
double USphere::GetInsideRadius() const
|
||||
{
|
||||
return fRmin;
|
||||
}
|
||||
|
||||
inline
|
||||
double USphere::GetInnerRadius() const
|
||||
{
|
||||
return fRmin;
|
||||
}
|
||||
|
||||
inline
|
||||
double USphere::GetOuterRadius() const
|
||||
{
|
||||
return fRmax;
|
||||
}
|
||||
|
||||
inline
|
||||
double USphere::GetStartPhiAngle() const
|
||||
{
|
||||
return fSPhi;
|
||||
}
|
||||
|
||||
inline
|
||||
double USphere::GetDeltaPhiAngle() const
|
||||
{
|
||||
return fDPhi;
|
||||
}
|
||||
|
||||
inline
|
||||
double USphere::GetStartThetaAngle() const
|
||||
{
|
||||
return fSTheta;
|
||||
}
|
||||
|
||||
double USphere::GetDeltaThetaAngle() const
|
||||
{
|
||||
return fDTheta;
|
||||
}
|
||||
|
||||
inline
|
||||
void USphere::Initialize()
|
||||
{
|
||||
fCubicVolume = 0.;
|
||||
fSurfaceArea = 0.;
|
||||
}
|
||||
|
||||
inline
|
||||
void USphere::InitializePhiTrigonometry()
|
||||
{
|
||||
hDPhi = 0.5 * fDPhi; // half delta phi
|
||||
cPhi = fSPhi + hDPhi;
|
||||
ePhi = fSPhi + fDPhi;
|
||||
|
||||
sinCPhi = std::sin(cPhi);
|
||||
cosCPhi = std::cos(cPhi);
|
||||
cosHDPhiIT = std::cos(hDPhi - 0.5 * kAngTolerance); // inner/outer tol half dphi
|
||||
cosHDPhiOT = std::cos(hDPhi + 0.5 * kAngTolerance);
|
||||
sinSPhi = std::sin(fSPhi);
|
||||
cosSPhi = std::cos(fSPhi);
|
||||
sinEPhi = std::sin(ePhi);
|
||||
cosEPhi = std::cos(ePhi);
|
||||
}
|
||||
|
||||
inline
|
||||
void USphere::InitializeThetaTrigonometry()
|
||||
{
|
||||
eTheta = fSTheta + fDTheta;
|
||||
|
||||
sinSTheta = std::sin(fSTheta);
|
||||
cosSTheta = std::cos(fSTheta);
|
||||
sinETheta = std::sin(eTheta);
|
||||
cosETheta = std::cos(eTheta);
|
||||
|
||||
tanSTheta = std::tan(fSTheta);
|
||||
tanSTheta2 = tanSTheta * tanSTheta;
|
||||
tanETheta = std::tan(eTheta);
|
||||
tanETheta2 = tanETheta * tanETheta;
|
||||
}
|
||||
|
||||
inline
|
||||
void USphere::CheckThetaAngles(double sTheta, double dTheta)
|
||||
{
|
||||
if ((sTheta < 0) || (sTheta > UUtils::kPi))
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "sTheta outside 0-PI range." << std::endl
|
||||
<< "Invalid starting Theta angle for solid: " << GetName();
|
||||
UUtils::Exception("USphere::CheckThetaAngles()", "GeomSolids0002",
|
||||
FatalError, 1, message.str().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
fSTheta = sTheta;
|
||||
}
|
||||
if (dTheta + sTheta >= UUtils::kPi)
|
||||
{
|
||||
fDTheta = UUtils::kPi - sTheta;
|
||||
}
|
||||
else if (dTheta > 0)
|
||||
{
|
||||
fDTheta = dTheta;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Invalid dTheta." << std::endl
|
||||
<< "Negative delta-Theta (" << dTheta << "), for solid: "
|
||||
<< GetName();
|
||||
UUtils::Exception("USphere::CheckThetaAngles()", "GeomSolids0002",
|
||||
FatalError, 1, message.str().c_str());
|
||||
}
|
||||
if (fDTheta - fSTheta < UUtils::kPi)
|
||||
{
|
||||
fFullThetaSphere = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
fFullThetaSphere = true ;
|
||||
}
|
||||
fFullSphere = fFullPhiSphere && fFullThetaSphere;
|
||||
|
||||
InitializeThetaTrigonometry();
|
||||
}
|
||||
|
||||
inline
|
||||
void USphere::CheckSPhiAngle(double sPhi)
|
||||
{
|
||||
// Ensure fSphi in 0-2PI or -2PI-0 range if shape crosses 0
|
||||
|
||||
if (sPhi < 0)
|
||||
{
|
||||
fSPhi = 2 * UUtils::kPi - std::fmod(std::fabs(sPhi), 2 * UUtils::kPi);
|
||||
}
|
||||
else
|
||||
{
|
||||
fSPhi = std::fmod(sPhi, 2 * UUtils::kPi) ;
|
||||
}
|
||||
if (fSPhi + fDPhi > 2 * UUtils::kPi)
|
||||
{
|
||||
fSPhi -= 2 * UUtils::kPi ;
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
void USphere::CheckDPhiAngle(double dPhi)
|
||||
{
|
||||
fFullPhiSphere = true;
|
||||
if (dPhi >= 2 * UUtils::kPi - kAngTolerance * 0.5)
|
||||
{
|
||||
fDPhi = 2 * UUtils::kPi;
|
||||
fSPhi = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
fFullPhiSphere = false;
|
||||
if (dPhi > 0)
|
||||
{
|
||||
fDPhi = dPhi;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Invalid dphi." << std::endl
|
||||
<< "Negative delta-Phi (" << dPhi << "), for solid: "
|
||||
<< GetName();
|
||||
UUtils::Exception("USphere::CheckDPhiAngle()", "GeomSolids0002",
|
||||
FatalError, 1, message.str().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
void USphere::CheckPhiAngles(double sPhi, double dPhi)
|
||||
{
|
||||
CheckDPhiAngle(dPhi);
|
||||
//if (!fFullPhiSphere && sPhi) { CheckSPhiAngle(sPhi); }
|
||||
if (!fFullPhiSphere)
|
||||
{
|
||||
CheckSPhiAngle(sPhi);
|
||||
}
|
||||
fFullSphere = fFullPhiSphere && fFullThetaSphere;
|
||||
|
||||
InitializePhiTrigonometry();
|
||||
}
|
||||
|
||||
inline
|
||||
void USphere::SetInsideRadius(double newRmin)
|
||||
{
|
||||
fRmin = newRmin;
|
||||
fRminTolerance = (fRmin) ? std::max(kRadTolerance, fEpsilon * fRmin) : 0;
|
||||
Initialize();
|
||||
}
|
||||
|
||||
inline
|
||||
void USphere::SetInnerRadius(double newRmin)
|
||||
{
|
||||
SetInsideRadius(newRmin);
|
||||
}
|
||||
|
||||
inline
|
||||
void USphere::SetOuterRadius(double newRmax)
|
||||
{
|
||||
fRmax = newRmax;
|
||||
kTolerance = std::max(kRadTolerance, fEpsilon * fRmax);
|
||||
Initialize();
|
||||
}
|
||||
|
||||
inline
|
||||
void USphere::SetStartPhiAngle(double newSPhi, bool compute)
|
||||
{
|
||||
// Flag 'compute' can be used to explicitely avoid recomputation of
|
||||
// trigonometry in case SetDeltaPhiAngle() is invoked afterwards
|
||||
|
||||
CheckSPhiAngle(newSPhi);
|
||||
fFullPhiSphere = false;
|
||||
if (compute)
|
||||
{
|
||||
InitializePhiTrigonometry();
|
||||
}
|
||||
Initialize();
|
||||
}
|
||||
|
||||
inline
|
||||
void USphere::SetDeltaPhiAngle(double newDPhi)
|
||||
{
|
||||
CheckPhiAngles(fSPhi, newDPhi);
|
||||
Initialize();
|
||||
}
|
||||
|
||||
inline
|
||||
void USphere::SetStartThetaAngle(double newSTheta)
|
||||
{
|
||||
CheckThetaAngles(newSTheta, fDTheta);
|
||||
Initialize();
|
||||
}
|
||||
|
||||
inline
|
||||
void USphere::SetDeltaThetaAngle(double newDTheta)
|
||||
{
|
||||
CheckThetaAngles(fSTheta, newDTheta);
|
||||
Initialize();
|
||||
}
|
||||
|
||||
// Old access functions
|
||||
|
||||
inline
|
||||
double USphere::GetRmin() const
|
||||
{
|
||||
return GetInsideRadius();
|
||||
}
|
||||
|
||||
inline
|
||||
double USphere::GetRmax() const
|
||||
{
|
||||
return GetOuterRadius();
|
||||
}
|
||||
|
||||
inline
|
||||
double USphere::GetSPhi() const
|
||||
{
|
||||
return GetStartPhiAngle();
|
||||
}
|
||||
|
||||
inline
|
||||
double USphere::GetDPhi() const
|
||||
{
|
||||
return GetDeltaPhiAngle();
|
||||
}
|
||||
|
||||
inline
|
||||
double USphere::GetSTheta() const
|
||||
{
|
||||
return GetStartThetaAngle();
|
||||
}
|
||||
|
||||
inline
|
||||
double USphere::GetDTheta() const
|
||||
{
|
||||
return GetDeltaThetaAngle();
|
||||
}
|
||||
|
||||
inline
|
||||
double USphere::Capacity()
|
||||
{
|
||||
if (fCubicVolume != 0.)
|
||||
{
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
fCubicVolume = fDPhi * (std::cos(fSTheta) - std::cos(fSTheta + fDTheta)) *
|
||||
(fRmax * fRmax * fRmax - fRmin * fRmin * fRmin) / 3.;
|
||||
}
|
||||
return fCubicVolume;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,143 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UTet
|
||||
//
|
||||
// Class description:
|
||||
//
|
||||
// A UTet is a tetrahedrasolid.
|
||||
//
|
||||
// 19.07.13 Tatiana Nikitina
|
||||
// Created from original implementation in Geant4
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#ifndef UTet_hh
|
||||
#define UTet_hh
|
||||
|
||||
#include "VUSolid.hh"
|
||||
#include "UUtils.hh"
|
||||
|
||||
class UTet : public VUSolid
|
||||
{
|
||||
|
||||
public: // with description
|
||||
|
||||
UTet(const std::string& name,
|
||||
UVector3 anchor,
|
||||
UVector3 p2,
|
||||
UVector3 p3,
|
||||
UVector3 p4,
|
||||
bool* degeneracyFlag = 0);
|
||||
|
||||
virtual ~UTet();
|
||||
|
||||
|
||||
// Methods for solid
|
||||
|
||||
EnumInside Inside(const UVector3& p) const;
|
||||
|
||||
bool Normal(const UVector3& aPoint, UVector3& aNormal) const;
|
||||
|
||||
double SafetyFromInside(const UVector3& aPoint,
|
||||
bool aAccurate = false) const;
|
||||
double SafetyFromOutside(const UVector3& aPoint,
|
||||
bool aAccurate = false) const;
|
||||
double DistanceToIn(const UVector3& aPoint,
|
||||
const UVector3& aDirection,
|
||||
// UVector3 &aNormalVector,
|
||||
double aPstep = UUtils::kInfinity) const;
|
||||
|
||||
double DistanceToOut(const UVector3& aPoint,
|
||||
const UVector3& aDirection,
|
||||
UVector3& aNormalVector,
|
||||
bool& aConvex,
|
||||
double aPstep = UUtils::kInfinity) const;
|
||||
|
||||
void Extent(UVector3& aMin, UVector3& aMax) const;
|
||||
|
||||
double Capacity();
|
||||
double SurfaceArea();
|
||||
|
||||
UGeometryType GetEntityType() const;
|
||||
|
||||
void ComputeBBox(UBBox* /*aBox*/, bool /*aStore = false*/) {}
|
||||
|
||||
//G4Visualisation
|
||||
void GetParametersList(int aNumber, double* aArray) const;
|
||||
|
||||
VUSolid* Clone() const
|
||||
{
|
||||
std::vector<UVector3> v = GetVertices();
|
||||
return new UTet(GetName(), v[0], v[1], v[2], v[3]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
UVector3 GetPointOnSurface() const;
|
||||
std::ostream& StreamInfo(std::ostream& os) const;
|
||||
|
||||
public: // without description
|
||||
|
||||
//UTet(__void__&);
|
||||
// Fake default constructor for usage restricted to direct object
|
||||
// persistency for clients requiring preallocation of memory for
|
||||
// persistifiable objects.
|
||||
|
||||
UTet(const UTet& rhs);
|
||||
UTet& operator=(const UTet& rhs);
|
||||
// Copy constructor and assignment operator.
|
||||
|
||||
const char* CVSHeaderVers()
|
||||
{
|
||||
return "$Id: G4Tet.hh 66356 2012-12-18 09:02:32Z gcosmo $";
|
||||
}
|
||||
const char* CVSFileVers()
|
||||
{
|
||||
return CVSVers;
|
||||
}
|
||||
void PrintWarnings(bool flag)
|
||||
{
|
||||
warningFlag = flag;
|
||||
}
|
||||
static bool CheckDegeneracy(UVector3& anchor,
|
||||
UVector3& p2,
|
||||
UVector3& p3,
|
||||
UVector3& p4);
|
||||
std::vector<UVector3> GetVertices() const;
|
||||
// Return the four vertices of the shape.
|
||||
|
||||
protected: // with description
|
||||
|
||||
/* UVectorList*
|
||||
CreateRotatedVertices(const G4AffineTransform& pTransform) const;
|
||||
// Create the List of transformed vertices in the format required
|
||||
// for G4VSolid:: ClipCrossSection and ClipBetweenSections.
|
||||
*/
|
||||
private:
|
||||
|
||||
double fCubicVolume, fSurfaceArea;
|
||||
|
||||
UVector3 GetPointOnFace(UVector3 p1, UVector3 p2,
|
||||
UVector3 p3, double& area) const;
|
||||
static const char CVSVers[];
|
||||
|
||||
private:
|
||||
|
||||
UVector3 fAnchor, fP2, fP3, fP4, fMiddle;
|
||||
UVector3 fNormal123, fNormal142, fNormal134, fNormal234;
|
||||
|
||||
bool warningFlag;
|
||||
|
||||
double fCdotN123, fCdotN142, fCdotN134, fCdotN234;
|
||||
double fXMin, fXMax, fYMin, fYMax, fZMin, fZMax;
|
||||
double fDx, fDy, fDz, fTol, fMaxSize;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,59 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UTransform3D
|
||||
//
|
||||
// Class description:
|
||||
//
|
||||
// UTransform3D: General transformation made by rotation + translation
|
||||
//
|
||||
// 19.10.12 Marek Gayer
|
||||
// Created from original implementation in CLHEP
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#ifndef USOLIDS_UTransform3D
|
||||
#define USOLIDS_UTransform3D
|
||||
|
||||
#include "UVector3.hh"
|
||||
|
||||
class UTransform3D
|
||||
{
|
||||
public:
|
||||
UVector3 fTr; // Translation
|
||||
double fRot[9]; // Rotation
|
||||
|
||||
|
||||
UTransform3D(); // Initialize to identity
|
||||
UTransform3D(double tx, double ty, double tz,
|
||||
double phi = 0., double theta = 0., double psi = 0.);
|
||||
UTransform3D(const UTransform3D& other);
|
||||
~UTransform3D() {}
|
||||
|
||||
virtual void RotateX(double angle);
|
||||
virtual void RotateY(double angle);
|
||||
virtual void RotateZ(double angle);
|
||||
void SetAngles(double phi, double theta, double psi);
|
||||
|
||||
// Local<->global coordinate and vector conversions
|
||||
UVector3 GlobalPoint(const UVector3& local) const;
|
||||
UVector3 GlobalVector(const UVector3& local) const;
|
||||
UVector3 LocalPoint(const UVector3& global) const;
|
||||
UVector3 LocalVector(const UVector3& global) const;
|
||||
|
||||
|
||||
// Operators
|
||||
UTransform3D& operator = (const UTransform3D& other);
|
||||
UTransform3D& operator *= (const UTransform3D& other);
|
||||
UTransform3D& operator *= (const UVector3& vect);
|
||||
};
|
||||
// Vector-matrix multiplication
|
||||
UVector3 operator * (const UVector3& p, const UTransform3D& trans);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,118 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UTrd
|
||||
//
|
||||
// Class description:
|
||||
//
|
||||
// A UTrd is a trapezoid with the x and y dimensions varying along z
|
||||
// functions.
|
||||
//
|
||||
// 19.10.12 Marek Gayer
|
||||
// Created from original implementation in Geant4
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#ifndef USOLIDS_UTrd
|
||||
#define USOLIDS_UTrd
|
||||
|
||||
#include "VUSolid.hh"
|
||||
#include "UUtils.hh"
|
||||
|
||||
class UTrd : public VUSolid
|
||||
{
|
||||
enum ESide {kUndefined, kPX, kMX, kPY, kMY, kPZ, kMZ};
|
||||
public:
|
||||
UTrd() : VUSolid(), fDx1(0), fDx2(0), fDy1(0), fDy2(0), fDz(0) {}
|
||||
UTrd(const std::string& pName, double pdx1, double pdx2, double pdy1, double pdy2, double pdz);
|
||||
virtual ~UTrd() {}
|
||||
|
||||
UTrd(const UTrd& rhs);
|
||||
UTrd& operator=(const UTrd& rhs);
|
||||
|
||||
// Copy constructor and assignment operator
|
||||
|
||||
// Accessors
|
||||
|
||||
inline double GetXHalfLength1() const;
|
||||
inline double GetXHalfLength2() const;
|
||||
inline double GetYHalfLength1() const;
|
||||
inline double GetYHalfLength2() const;
|
||||
inline double GetZHalfLength() const;
|
||||
|
||||
// Modifiers
|
||||
|
||||
inline void SetXHalfLength1(double val);
|
||||
inline void SetXHalfLength2(double val);
|
||||
inline void SetYHalfLength1(double val);
|
||||
inline void SetYHalfLength2(double val);
|
||||
inline void SetZHalfLength(double val);
|
||||
// Navigation methods
|
||||
EnumInside Inside(const UVector3& aPoint) const;
|
||||
|
||||
virtual double SafetyFromInside(const UVector3& aPoint, bool aAccurate = false) const;
|
||||
|
||||
inline double SafetyFromInsideAccurate(const UVector3& aPoint) const;
|
||||
|
||||
virtual double SafetyFromOutside(const UVector3& aPoint, bool aAccurate = false) const;
|
||||
|
||||
inline double SafetyFromOutsideAccurate(const UVector3& aPoint) const;
|
||||
|
||||
virtual double DistanceToIn(const UVector3& aPoint,
|
||||
const UVector3& aDirection,
|
||||
// UVector3 &aNormalVector,
|
||||
double aPstep = UUtils::kInfinity) const;
|
||||
|
||||
|
||||
virtual double DistanceToOut(const UVector3& aPoint,
|
||||
const UVector3& aDirection,
|
||||
UVector3& aNormalVector,
|
||||
bool& aConvex,
|
||||
double aPstep = UUtils::kInfinity) const;
|
||||
|
||||
virtual bool Normal(const UVector3& aPoint, UVector3& aNormal) const;
|
||||
|
||||
void CheckAndSetAllParameters ( double pdx1, double pdx2,
|
||||
double pdy1, double pdy2,
|
||||
double pdz );
|
||||
|
||||
void SetAllParameters ( double pdx1, double pdx2,
|
||||
double pdy1, double pdy2,
|
||||
double pdz );
|
||||
|
||||
// virtual void Extent ( EAxisType aAxis, double &aMin, double &aMax ) const;
|
||||
void Extent(UVector3& aMin, UVector3& aMax) const;
|
||||
inline double Capacity();
|
||||
inline double SurfaceArea();
|
||||
inline VUSolid* Clone() const
|
||||
{
|
||||
return new UTrd(GetName(), fDx1, fDx2, fDy1, fDy2, fDz);
|
||||
}
|
||||
UGeometryType GetEntityType() const;
|
||||
|
||||
virtual void ComputeBBox(UBBox* /*aBox*/, bool /*aStore = false*/) {}
|
||||
|
||||
//G4Visualisation
|
||||
virtual void GetParametersList(int /*aNumber*/, double* /*aArray*/) const;
|
||||
std::ostream& StreamInfo(std::ostream& os) const;
|
||||
|
||||
UVector3 GetPointOnSurface() const;
|
||||
|
||||
private:
|
||||
inline UVector3 ApproxSurfaceNormal(const UVector3& p) const;
|
||||
inline double amin(int n, const double* a) const;
|
||||
inline double amax(int n, const double* a)const;
|
||||
double fDx1, fDx2, fDy1, fDy2, fDz;
|
||||
double fCubicVolume; // Cubic Volume
|
||||
double fSurfaceArea; // Surface Area
|
||||
};
|
||||
|
||||
#include "UTrd.icc"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,142 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UTrd.icc
|
||||
//
|
||||
// Implementation of inline methods of UTrd
|
||||
//
|
||||
// 19.10.12 Marek Gayer
|
||||
// Created from original implementation in Geant4
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
inline
|
||||
double UTrd::GetXHalfLength1() const
|
||||
{
|
||||
return fDx1;
|
||||
}
|
||||
|
||||
inline
|
||||
double UTrd::GetXHalfLength2() const
|
||||
{
|
||||
return fDx2;
|
||||
}
|
||||
|
||||
inline
|
||||
double UTrd::GetYHalfLength1() const
|
||||
{
|
||||
return fDy1;
|
||||
}
|
||||
|
||||
inline
|
||||
double UTrd::GetYHalfLength2() const
|
||||
{
|
||||
return fDy2;
|
||||
}
|
||||
|
||||
inline
|
||||
double UTrd::GetZHalfLength() const
|
||||
{
|
||||
return fDz;
|
||||
}
|
||||
|
||||
inline
|
||||
void UTrd::SetXHalfLength1(double val)
|
||||
{
|
||||
fDx1 = val;
|
||||
fCubicVolume = 0.;
|
||||
fSurfaceArea = 0;
|
||||
|
||||
}
|
||||
|
||||
inline
|
||||
void UTrd::SetXHalfLength2(double val)
|
||||
{
|
||||
fDx2 = val;
|
||||
fCubicVolume = 0.;
|
||||
fSurfaceArea = 0;
|
||||
}
|
||||
|
||||
inline
|
||||
void UTrd::SetYHalfLength1(double val)
|
||||
{
|
||||
fDy1 = val;
|
||||
fCubicVolume = 0.;
|
||||
fSurfaceArea = 0;
|
||||
}
|
||||
|
||||
inline
|
||||
void UTrd::SetYHalfLength2(double val)
|
||||
{
|
||||
fDy2 = val;
|
||||
fCubicVolume = 0.;
|
||||
fSurfaceArea = 0;
|
||||
|
||||
}
|
||||
|
||||
inline
|
||||
void UTrd::SetZHalfLength(double val)
|
||||
{
|
||||
fDz = val;
|
||||
fCubicVolume = 0.;
|
||||
fSurfaceArea = 0;
|
||||
|
||||
}
|
||||
|
||||
inline
|
||||
double UTrd::Capacity()
|
||||
{
|
||||
if (fCubicVolume != 0.)
|
||||
{
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
fCubicVolume = 2 * fDz * ((fDx1 + fDx2) * (fDy1 + fDy2)
|
||||
+ (fDx2 - fDx1) * (fDy2 - fDy1) / 3);
|
||||
}
|
||||
return fCubicVolume;
|
||||
}
|
||||
|
||||
inline
|
||||
double UTrd::SurfaceArea()
|
||||
{
|
||||
if (fSurfaceArea != 0.)
|
||||
{
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
fSurfaceArea = 4 * (fDx1 * fDy1 + fDx2 * fDy2)
|
||||
+ 2 * ((fDy1 + fDy2) * std::sqrt(4 * fDz * fDz + (fDx2 - fDx1) * (fDx2 - fDx1))
|
||||
+ (fDx1 + fDx2) * std::sqrt(4 * fDz * fDz + (fDy2 - fDy1) * (fDy2 - fDy1)));
|
||||
}
|
||||
return fSurfaceArea;
|
||||
}
|
||||
inline double UTrd::amin(int n, const double* a) const
|
||||
{
|
||||
// Return value from array with the minimum element.
|
||||
double xmin = a[0];
|
||||
for (int i = 1; i < n; i++)
|
||||
{
|
||||
if (xmin > a[i]) xmin = a[i];
|
||||
}
|
||||
return xmin;
|
||||
}
|
||||
|
||||
inline double UTrd::amax(int n, const double* a)const
|
||||
{
|
||||
// Return value from array with the maximum element.
|
||||
double xmax = a[0];
|
||||
for (int i = 1; i < n; i++)
|
||||
{
|
||||
if (xmax < a[i]) xmax = a[i];
|
||||
}
|
||||
return xmax;
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UTubs
|
||||
//
|
||||
// Class description:
|
||||
//
|
||||
// A tube or tube segment with curved sides parallel to
|
||||
// the z-axis. The tube has a specified half-length along
|
||||
// the z-axis, about which it is centered, and a given
|
||||
// minimum and maximum radius. A minimum radius of 0
|
||||
// corresponds to filled tube /cylinder. The tube segment is
|
||||
// specified by starting and delta angles for phi, with 0
|
||||
// being the +x axis, PI/2 the +y axis.
|
||||
// A delta angle of 2PI signifies a complete, unsegmented
|
||||
// tube/cylinder.
|
||||
//
|
||||
// Member Data:
|
||||
//
|
||||
// fRMin Inner radius
|
||||
// fRMax Outer radius
|
||||
// fDz half length in z
|
||||
//
|
||||
// fSPhi The starting phi angle in radians,
|
||||
// adjusted such that fSPhi+fDPhi<=2PI, fSPhi>-2PI
|
||||
//
|
||||
// fDPhi Delta angle of the segment.
|
||||
//
|
||||
// fPhiFullTube Boolean variable used for indicate the Phi Section
|
||||
//
|
||||
// 19.10.12 Marek Gayer
|
||||
// Created from original implementation in Geant4
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#ifndef UTUBS_HH
|
||||
#define UTUBS_HH
|
||||
|
||||
#include "VUSolid.hh"
|
||||
|
||||
class UTubs : public VUSolid
|
||||
{
|
||||
public: // with description
|
||||
|
||||
UTubs(const std::string& pName,
|
||||
double pRMin,
|
||||
double pRMax,
|
||||
double pDz,
|
||||
double pSPhi,
|
||||
double pDPhi);
|
||||
//
|
||||
// Constructs a tubs with the given name and dimensions
|
||||
|
||||
virtual ~UTubs();
|
||||
//
|
||||
// Destructor
|
||||
|
||||
// Accessors
|
||||
|
||||
inline double GetInnerRadius() const;
|
||||
inline double GetOuterRadius() const;
|
||||
inline double GetZHalfLength() const;
|
||||
inline double GetStartPhiAngle() const;
|
||||
inline double GetDeltaPhiAngle() const;
|
||||
|
||||
// Modifiers
|
||||
|
||||
inline void SetInnerRadius(double newRMin);
|
||||
inline void SetOuterRadius(double newRMax);
|
||||
inline void SetZHalfLength(double newDz);
|
||||
inline void SetStartPhiAngle(double newSPhi, bool trig = true);
|
||||
inline void SetDeltaPhiAngle(double newDPhi);
|
||||
|
||||
// Methods for solid
|
||||
|
||||
inline double Capacity();
|
||||
inline double SurfaceArea();
|
||||
|
||||
inline VUSolid::EnumInside Inside(const UVector3& p) const;
|
||||
|
||||
bool Normal(const UVector3& p, UVector3& normal) const;
|
||||
|
||||
double DistanceToIn(const UVector3& p, const UVector3& v, double aPstep = UUtils::kInfinity) const;
|
||||
double SafetyFromInside(const UVector3& p, bool precise = false) const;
|
||||
double DistanceToOut(const UVector3& p, const UVector3& v, UVector3& n, bool& validNorm, double aPstep = UUtils::kInfinity) const;
|
||||
double SafetyFromOutside(const UVector3& p, bool precise = false) const;
|
||||
|
||||
UGeometryType GetEntityType() const;
|
||||
|
||||
UVector3 GetPointOnSurface() const;
|
||||
|
||||
VUSolid* Clone() const;
|
||||
|
||||
std::ostream& StreamInfo(std::ostream& os) const;
|
||||
|
||||
// void Extent (EAxisType aAxis, double &aMin, double &aMax) const;
|
||||
void Extent(UVector3& aMin, UVector3& aMax) const;
|
||||
|
||||
virtual void GetParametersList(int /*aNumber*/, double* /*aArray*/) const;
|
||||
virtual void ComputeBBox(UBBox* /*aBox*/, bool /*aStore = false*/) {}
|
||||
|
||||
public: // without description
|
||||
|
||||
UTubs();
|
||||
//
|
||||
// Fake default constructor for usage restricted to direct object
|
||||
// persistency for clients requiring preallocation of memory for
|
||||
// persistifiable objects.
|
||||
|
||||
UTubs(const UTubs& rhs);
|
||||
UTubs& operator=(const UTubs& rhs);
|
||||
// Copy constructor and assignment operator.
|
||||
|
||||
// Older names for access functions
|
||||
|
||||
inline double GetRMin() const;
|
||||
inline double GetRMax() const;
|
||||
inline double GetDz() const;
|
||||
inline double GetSPhi() const;
|
||||
inline double GetDPhi() const;
|
||||
|
||||
protected:
|
||||
|
||||
// UVector3List*
|
||||
// CreateRotatedVertices( const UAffineTransform& pTransform ) const;
|
||||
//
|
||||
// Creates the List of transformed vertices in the format required
|
||||
// for VUSolid:: ClipCrossSection and ClipBetweenSections
|
||||
|
||||
inline void Initialize();
|
||||
//
|
||||
// Reset relevant values to zero
|
||||
|
||||
inline void CheckSPhiAngle(double sPhi);
|
||||
inline void CheckDPhiAngle(double dPhi);
|
||||
inline void CheckPhiAngles(double sPhi, double dPhi);
|
||||
//
|
||||
// Reset relevant flags and angle values
|
||||
|
||||
inline void InitializeTrigonometry();
|
||||
//
|
||||
// Recompute relevant trigonometric values and cache them
|
||||
|
||||
virtual UVector3 ApproxSurfaceNormal(const UVector3& p) const;
|
||||
//
|
||||
// Algorithm for SurfaceNormal() following the original
|
||||
// specification for points not on the surface
|
||||
|
||||
protected:
|
||||
|
||||
double fCubicVolume, fSurfaceArea;
|
||||
// Used by distanceToOut
|
||||
//
|
||||
enum ESide {kNull, kRMin, kRMax, kSPhi, kEPhi, kPZ, kMZ};
|
||||
|
||||
// Used by normal
|
||||
//
|
||||
enum ENorm {kNRMin, kNRMax, kNSPhi, kNEPhi, kNZ};
|
||||
|
||||
double kRadTolerance, kAngTolerance;
|
||||
//
|
||||
// Radial and angular tolerances
|
||||
|
||||
double fRMin, fRMax, fDz, fSPhi, fDPhi;
|
||||
//
|
||||
// Radial and angular dimensions
|
||||
|
||||
double fSinCPhi, fCosCPhi, fCosHDPhiOT, fCosHDPhiIT,
|
||||
fSinSPhi, fCosSPhi, fSinEPhi, fCosEPhi, fSinSPhiDPhi, fCosSPhiDPhi;
|
||||
//
|
||||
// Cached trigonometric values
|
||||
|
||||
bool fPhiFullTube;
|
||||
//
|
||||
// Flag for identification of section or full tube
|
||||
};
|
||||
|
||||
#include "UTubs.icc"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,267 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UTubs.icc
|
||||
//
|
||||
// Implementation of inline methods of UTubs
|
||||
//
|
||||
// 19.10.12 Marek Gayer
|
||||
// Created from original implementation in Geant4
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
inline
|
||||
double UTubs::GetInnerRadius() const
|
||||
{
|
||||
return fRMin;
|
||||
}
|
||||
|
||||
inline
|
||||
double UTubs::GetOuterRadius() const
|
||||
{
|
||||
return fRMax;
|
||||
}
|
||||
|
||||
inline
|
||||
double UTubs::GetZHalfLength() const
|
||||
{
|
||||
return fDz;
|
||||
}
|
||||
|
||||
inline
|
||||
double UTubs::GetStartPhiAngle() const
|
||||
{
|
||||
return fSPhi;
|
||||
}
|
||||
|
||||
inline
|
||||
double UTubs::GetDeltaPhiAngle() const
|
||||
{
|
||||
return fDPhi;
|
||||
}
|
||||
|
||||
inline
|
||||
void UTubs::Initialize()
|
||||
{
|
||||
fCubicVolume = 0.;
|
||||
fSurfaceArea = 0.;
|
||||
}
|
||||
|
||||
inline
|
||||
void UTubs::InitializeTrigonometry()
|
||||
{
|
||||
double hDPhi = 0.5 * fDPhi; // half delta phi
|
||||
double cPhi = fSPhi + hDPhi;
|
||||
double ePhi = fSPhi + fDPhi;
|
||||
|
||||
fSinCPhi = std::sin(cPhi);
|
||||
fCosCPhi = std::cos(cPhi);
|
||||
fCosHDPhiIT = std::cos(hDPhi - 0.5 * kAngTolerance); // inner/outer tol half dphi
|
||||
fCosHDPhiOT = std::cos(hDPhi + 0.5 * kAngTolerance);
|
||||
fSinSPhi = std::sin(fSPhi);
|
||||
fCosSPhi = std::cos(fSPhi);
|
||||
fSinEPhi = std::sin(ePhi);
|
||||
fCosEPhi = std::cos(ePhi);
|
||||
|
||||
fSinSPhiDPhi = std::sin(fSPhi + fDPhi);
|
||||
fCosSPhiDPhi = std::cos(fSPhi + fDPhi);
|
||||
}
|
||||
|
||||
inline void UTubs::CheckSPhiAngle(double sPhi)
|
||||
{
|
||||
// Ensure fSphi in 0-2PI or -2PI-0 range if shape crosses 0
|
||||
|
||||
if (sPhi < 0)
|
||||
{
|
||||
fSPhi = 2 * UUtils::kPi - std::fmod(std::fabs(sPhi), 2 * UUtils::kPi);
|
||||
}
|
||||
else
|
||||
{
|
||||
fSPhi = std::fmod(sPhi, 2 * UUtils::kPi) ;
|
||||
}
|
||||
if (fSPhi + fDPhi > 2 * UUtils::kPi)
|
||||
{
|
||||
fSPhi -= 2 * UUtils::kPi ;
|
||||
}
|
||||
}
|
||||
|
||||
inline void UTubs::CheckDPhiAngle(double dPhi)
|
||||
{
|
||||
fPhiFullTube = true;
|
||||
if (dPhi >= 2 * UUtils::kPi - kAngTolerance * 0.5)
|
||||
{
|
||||
fDPhi = 2 * UUtils::kPi;
|
||||
fSPhi = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
fPhiFullTube = false;
|
||||
if (dPhi > 0)
|
||||
{
|
||||
fDPhi = dPhi;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Invalid dphi." << std::endl
|
||||
<< "Negative or zero delta-Phi (" << dPhi << "), for solid: "
|
||||
<< GetName();
|
||||
UUtils::Exception("UTubs::CheckDPhiAngle()", "GeomSolids0002",
|
||||
FatalError, 1, message.str().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void UTubs::CheckPhiAngles(double sPhi, double dPhi)
|
||||
{
|
||||
CheckDPhiAngle(dPhi);
|
||||
if ((fDPhi < 2 * UUtils::kPi) && (sPhi))
|
||||
{
|
||||
CheckSPhiAngle(sPhi);
|
||||
}
|
||||
InitializeTrigonometry();
|
||||
}
|
||||
|
||||
inline
|
||||
void UTubs::SetInnerRadius(double newRMin)
|
||||
{
|
||||
if (newRMin < 0) // Check radii
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Invalid radii." << std::endl
|
||||
<< "Invalid values for radii in solid " << GetName() << std::endl
|
||||
<< " newRMin = " << newRMin
|
||||
<< ", fRMax = " << fRMax << std::endl
|
||||
<< " Negative inner radius!";
|
||||
UUtils::Exception("UTubs::SetInnerRadius()", "GeomSolids0002",
|
||||
FatalError, 1, message.str().c_str());
|
||||
}
|
||||
fRMin = newRMin;
|
||||
Initialize();
|
||||
}
|
||||
|
||||
inline
|
||||
void UTubs::SetOuterRadius(double newRMax)
|
||||
{
|
||||
if (newRMax <= 0) // Check radii
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Invalid radii." << std::endl
|
||||
<< "Invalid values for radii in solid " << GetName() << std::endl
|
||||
<< " fRMin = " << fRMin
|
||||
<< ", newRMax = " << newRMax << std::endl
|
||||
<< " Invalid outer radius!";
|
||||
UUtils::Exception("UTubs::SetOuterRadius()", "GeomSolids0002",
|
||||
FatalError, 1, message.str().c_str());
|
||||
}
|
||||
fRMax = newRMax;
|
||||
Initialize();
|
||||
}
|
||||
|
||||
inline
|
||||
void UTubs::SetZHalfLength(double newDz)
|
||||
{
|
||||
if (newDz <= 0) // Check z-len
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Invalid Z half-length." << std::endl
|
||||
<< "Negative Z half-length (" << newDz << "), for solid: "
|
||||
<< GetName();
|
||||
UUtils::Exception("UTubs::SetZHalfLength()", "GeomSolids0002",
|
||||
FatalError, 1, message.str().c_str());
|
||||
}
|
||||
fDz = newDz;
|
||||
Initialize();
|
||||
}
|
||||
|
||||
inline
|
||||
void UTubs::SetStartPhiAngle(double newSPhi, bool compute)
|
||||
{
|
||||
// Flag 'compute' can be used to explicitely avoid recomputation of
|
||||
// trigonometry in case SetDeltaPhiAngle() is invoked afterwards
|
||||
|
||||
CheckSPhiAngle(newSPhi);
|
||||
fPhiFullTube = false;
|
||||
if (compute)
|
||||
{
|
||||
InitializeTrigonometry();
|
||||
}
|
||||
Initialize();
|
||||
}
|
||||
|
||||
inline
|
||||
void UTubs::SetDeltaPhiAngle(double newDPhi)
|
||||
{
|
||||
CheckPhiAngles(fSPhi, newDPhi);
|
||||
Initialize();
|
||||
}
|
||||
|
||||
// Older names for access functions
|
||||
|
||||
inline
|
||||
double UTubs::GetRMin() const
|
||||
{
|
||||
return GetInnerRadius();
|
||||
}
|
||||
|
||||
inline
|
||||
double UTubs::GetRMax() const
|
||||
{
|
||||
return GetOuterRadius();
|
||||
}
|
||||
|
||||
inline
|
||||
double UTubs::GetDz() const
|
||||
{
|
||||
return GetZHalfLength() ;
|
||||
}
|
||||
|
||||
inline
|
||||
double UTubs::GetSPhi() const
|
||||
{
|
||||
return GetStartPhiAngle();
|
||||
}
|
||||
|
||||
inline
|
||||
double UTubs::GetDPhi() const
|
||||
{
|
||||
return GetDeltaPhiAngle();
|
||||
}
|
||||
|
||||
inline
|
||||
double UTubs::Capacity()
|
||||
{
|
||||
if (fCubicVolume != 0.)
|
||||
{
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
fCubicVolume = fDPhi * fDz * (fRMax * fRMax - fRMin * fRMin);
|
||||
}
|
||||
return fCubicVolume;
|
||||
}
|
||||
|
||||
inline
|
||||
double UTubs::SurfaceArea()
|
||||
{
|
||||
if (fSurfaceArea != 0.)
|
||||
{
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
fSurfaceArea = fDPhi * (fRMin + fRMax) * (2 * fDz + fRMax - fRMin);
|
||||
if (!fPhiFullTube)
|
||||
{
|
||||
fSurfaceArea = fSurfaceArea + 4 * fDz * (fRMax - fRMin);
|
||||
}
|
||||
}
|
||||
return fSurfaceArea;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UTypes
|
||||
//
|
||||
// Description:
|
||||
//
|
||||
// Internal utility types defined for the unified solids library
|
||||
//
|
||||
// 19.10.12 Marek Gayer
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#ifndef USOLIDS_Utypes
|
||||
#define USOLIDS_Utypes
|
||||
|
||||
#include "UVector3.hh"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class __void__;
|
||||
|
||||
typedef unsigned int UInt_t;
|
||||
|
||||
struct UBBoxStruct
|
||||
{
|
||||
double extent[3]; // half-lengths on the 3 axis (arrays for indexing)
|
||||
double orig[3]; // center coordinates
|
||||
};
|
||||
|
||||
/*struct UBuffer3DStruct {
|
||||
const int fType; // Primitive type - predefined ones in TBuffer3DTypes.h
|
||||
|
||||
UInt_t fNbPnts; // Number of points describing the shape
|
||||
UInt_t fNbSegs; // Number of segments describing the shape
|
||||
UInt_t fNbPols; // Number of polygons describing the shape
|
||||
|
||||
UInt_t fPntsCapacity; // Current capacity of fPnts space
|
||||
UInt_t fSegsCapacity; // Current capacity of fSegs space
|
||||
UInt_t fPolsCapacity; // Current capacity of fSegs space
|
||||
|
||||
UInt_t fSections; // Section validity flags
|
||||
double *fPnts; // x0, y0, z0, x1, y1, z1, ..... ..... ....
|
||||
int *fSegs; // c0, p0, q0, c1, p1, q1, ..... ..... ....
|
||||
int *fPols; // c0, n0, s0, s1, ... sn, c1, n1, s0, ... sn
|
||||
};
|
||||
*/
|
||||
/*
|
||||
struct UFacet2{
|
||||
UInt_t f1;//number of vertices from verticesList forming a facet
|
||||
UInt_t f2;
|
||||
UInt_t f3;
|
||||
UInt_t f4;
|
||||
};
|
||||
struct UPolyhedron2{
|
||||
std::vector<UVector3> vertices;//List of Vertices for Polyhedron used in G4Vis
|
||||
std::vector<UFacet2> facets;//List of Facets;
|
||||
};
|
||||
*/
|
||||
|
||||
typedef UBBoxStruct UBBox;
|
||||
//typedef UBuffer3DStruct UBuffer3D;
|
||||
typedef std::string UGeometryType;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,234 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UUtils
|
||||
//
|
||||
// Description:
|
||||
//
|
||||
// Utility namespace providing common constants and mathematical utilities.
|
||||
//
|
||||
// 19.10.12 Marek Gayer
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#ifndef USOLIDS_UUtils
|
||||
#define USOLIDS_UUtils
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <limits>
|
||||
#include <cmath>
|
||||
#include <cfloat>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include "UVector3.hh"
|
||||
|
||||
class UTransform3D;
|
||||
|
||||
enum ExceptionSeverity
|
||||
{ FatalError, FatalErrorInArguments, Error, Warning, Info };
|
||||
|
||||
namespace UUtils
|
||||
{
|
||||
|
||||
// Sign
|
||||
inline short Sign(short a, short b);
|
||||
inline int Sign(int a, int b);
|
||||
inline long Sign(long a, long b);
|
||||
inline float Sign(float a, float b);
|
||||
inline double Sign(double a, double b);
|
||||
|
||||
// Trigonometric
|
||||
static const double kPi = 3.14159265358979323846;
|
||||
static const double kTwoPi = 2.0 * kPi;
|
||||
static const double kRadToDeg = 180.0 / kPi;
|
||||
static const double kDegToRad = kPi / 180.0;
|
||||
static const double kSqrt2 = 1.4142135623730950488016887242097;
|
||||
static const double kInfinity = DBL_MAX;
|
||||
|
||||
static const double kMeshAngleDefault = (kPi / 4); // Angle for mesh `wedges' in rads
|
||||
static const int kMinMeshSections = 3; // Min wedges+1 to make
|
||||
static const int kMaxMeshSections = 37; // max wedges+1 to make
|
||||
|
||||
inline double Infinity();
|
||||
|
||||
inline double ASin(double);
|
||||
inline double ACos(double);
|
||||
inline double ATan(double);
|
||||
inline double ATan2(double, double);
|
||||
|
||||
//Warnings and Errors Messages
|
||||
void Exception(const char* originOfException,
|
||||
const char* exceptionCode,
|
||||
ExceptionSeverity severity,
|
||||
int level,
|
||||
const char* description);
|
||||
|
||||
|
||||
// Comparing floating points
|
||||
inline bool AreEqualAbs(double af, double bf, double epsilon)
|
||||
{
|
||||
//return true if absolute difference between af and bf is less than epsilon
|
||||
return std::abs(af - bf) < epsilon;
|
||||
}
|
||||
inline bool AreEqualRel(double af, double bf, double relPrec)
|
||||
{
|
||||
//return true if relative difference between af and bf is less than relPrec
|
||||
return std::abs(af - bf) <= 0.5 * relPrec * (std::abs(af) + std::abs(bf));
|
||||
}
|
||||
|
||||
// Locate Min, Max element number in an array
|
||||
long LocMin(long n, const double* a);
|
||||
long LocMax(long n, const double* a);
|
||||
|
||||
// TransformLimits: Use the transformation to convert the local limits defined
|
||||
// by min/max vectors to the master frame. Returns modified limits.
|
||||
void TransformLimits(UVector3& min, UVector3& max, const UTransform3D& transformation);
|
||||
|
||||
double Random(double min = 0.0, double max = 1.0);
|
||||
|
||||
// Templates:
|
||||
template<typename T>
|
||||
struct CompareDesc
|
||||
{
|
||||
|
||||
CompareDesc(T d) : fData(d) {}
|
||||
|
||||
template<typename Index>
|
||||
bool operator()(Index i1, Index i2)
|
||||
{
|
||||
return *(fData + i1) > *(fData + i2);
|
||||
}
|
||||
|
||||
T fData;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct CompareAsc
|
||||
{
|
||||
|
||||
CompareAsc(T d) : fData(d) {}
|
||||
|
||||
template<typename Index>
|
||||
bool operator()(Index i1, Index i2)
|
||||
{
|
||||
return *(fData + i1) < *(fData + i2);
|
||||
}
|
||||
|
||||
T fData;
|
||||
};
|
||||
|
||||
int SaveVectorToExternalFile(const std::vector<double>& vector, const std::string& filename);
|
||||
int SaveVectorToExternalFile(const std::vector<UVector3>& vector, const std::string& filename);
|
||||
int SaveVectorToExternalFile(const std::vector<int>& vector, const std::string& filename);
|
||||
|
||||
std::string ToString(int number);
|
||||
std::string ToString(double number);
|
||||
|
||||
int FileSize(const std::string& filePath);
|
||||
|
||||
int StrPos(const std::string& haystack, const std::string& needle);
|
||||
|
||||
inline double GetRadiusInRing(double rmin, double rmax);
|
||||
|
||||
template <class T>
|
||||
inline T sqr(const T& x)
|
||||
{
|
||||
return x * x;
|
||||
}
|
||||
|
||||
inline bool StrEnds(std::string const& fullString, std::string const& ending)
|
||||
{
|
||||
if (fullString.length() >= ending.length())
|
||||
{
|
||||
return (0 == fullString.compare(fullString.length() - ending.length(), ending.length(), ending));
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline double UUtils::GetRadiusInRing(double rmin, double rmax)
|
||||
{
|
||||
// Generate radius in annular ring according to uniform area
|
||||
//
|
||||
if (rmin <= 0.)
|
||||
{
|
||||
return rmax * std::sqrt(Random());
|
||||
}
|
||||
if (rmin != rmax)
|
||||
{
|
||||
return std::sqrt(Random()
|
||||
* (sqr(rmax) - sqr(rmin)) + sqr(rmin));
|
||||
}
|
||||
return rmin;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________
|
||||
inline double UUtils::Infinity()
|
||||
{
|
||||
// returns an infinity as defined by the IEEE standard
|
||||
return std::numeric_limits<double>::infinity();
|
||||
}
|
||||
|
||||
//---- Sign --------------------------------------------------------------------
|
||||
inline short UUtils::Sign(short a, short b)
|
||||
{
|
||||
return (b >= 0) ? std::abs(a) : -std::abs(a);
|
||||
}
|
||||
|
||||
inline int UUtils::Sign(int a, int b)
|
||||
{
|
||||
return (b >= 0) ? std::abs(a) : -std::abs(a);
|
||||
}
|
||||
|
||||
inline long UUtils::Sign(long a, long b)
|
||||
{
|
||||
return (b >= 0) ? std::abs(a) : -std::abs(a);
|
||||
}
|
||||
|
||||
inline float UUtils::Sign(float a, float b)
|
||||
{
|
||||
return (b >= 0) ? std::abs(a) : -std::abs(a);
|
||||
}
|
||||
|
||||
inline double UUtils::Sign(double a, double b)
|
||||
{
|
||||
return (b >= 0) ? std::abs(a) : -std::abs(a);
|
||||
}
|
||||
|
||||
|
||||
//---- Trigonometric------------------------------------------------------------
|
||||
inline double UUtils::ASin(double x)
|
||||
{
|
||||
if (x < -1.) return -kPi / 2;
|
||||
if (x > 1.) return kPi / 2;
|
||||
return std::asin(x);
|
||||
}
|
||||
|
||||
inline double UUtils::ACos(double x)
|
||||
{
|
||||
if (x < -1.) return kPi;
|
||||
if (x > 1.) return 0;
|
||||
return std::acos(x);
|
||||
}
|
||||
|
||||
|
||||
inline double UUtils::ATan2(double y, double x)
|
||||
{
|
||||
if (x != 0) return std::atan2(y, x);
|
||||
if (y == 0) return 0;
|
||||
if (y > 0) return kPi / 2;
|
||||
else return -kPi / 2;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,68 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UVCSGface
|
||||
//
|
||||
// Class description:
|
||||
//
|
||||
// Definition of the virtual base class UVCSGface, one side (or face)
|
||||
// of a CSG-like solid. It should be possible to build a CSG entirely out of
|
||||
// connecting CSG faces.
|
||||
// Each face has an inside and outside surface, the former represents
|
||||
// the inside of the volume, the latter, the outside.
|
||||
//
|
||||
// 19.09.13 Marek Gayer
|
||||
// Created from original implementation in Geant4
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#ifndef UVCSGface_hh
|
||||
#define UVCSGface_hh
|
||||
|
||||
#include "UTypes.hh"
|
||||
#include "VUSolid.hh"
|
||||
|
||||
class UVoxelLimits;
|
||||
class UAffineTransform;
|
||||
class USolidExtentList;
|
||||
|
||||
class UVCSGface
|
||||
{
|
||||
public: // with description
|
||||
|
||||
UVCSGface() {}
|
||||
virtual ~UVCSGface() {}
|
||||
|
||||
virtual bool Distance(const UVector3& p, const UVector3& v,
|
||||
bool outgoing, double surfTolerance,
|
||||
double& distance, double& distFromSurface,
|
||||
UVector3& normal, bool& allBehind) = 0;
|
||||
|
||||
virtual double Safety(const UVector3& p, bool outgoing) = 0;
|
||||
|
||||
virtual VUSolid::EnumInside Inside(const UVector3& p, double tolerance,
|
||||
double* bestDistance) = 0;
|
||||
|
||||
virtual UVector3 Normal(const UVector3& p,
|
||||
double* bestDistance) = 0;
|
||||
|
||||
virtual double Extent(const UVector3 axis) = 0;
|
||||
|
||||
/* virtual void CalculateExtent( const EAxisType axis,
|
||||
const UVoxelLimits &voxelLimit,
|
||||
const UAffineTransform &tranform,
|
||||
USolidExtentList &extentList ) = 0;*/
|
||||
|
||||
virtual UVCSGface* Clone() = 0;
|
||||
|
||||
virtual double SurfaceArea() = 0;
|
||||
virtual UVector3 GetPointOnFace() = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,145 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UVCSGfaceted
|
||||
//
|
||||
// Class description:
|
||||
//
|
||||
// Virtual class defining CSG-like type shape that is built entire
|
||||
// of UCSGface faces.
|
||||
//
|
||||
// 19.09.13 Marek Gayer
|
||||
// Created from original implementation in Geant4
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#ifndef UVCSGfaceted_hh
|
||||
#define UVCSGfaceted_hh
|
||||
|
||||
#include "VUSolid.hh"
|
||||
#include "UVoxelizer.hh"
|
||||
#include "UBox.hh"
|
||||
#include "UReduciblePolygon.hh"
|
||||
|
||||
class UVCSGface;
|
||||
class UVisExtent;
|
||||
|
||||
class UVCSGfaceted : public VUSolid
|
||||
{
|
||||
public: // with description
|
||||
|
||||
UVCSGfaceted(const std::string& name);
|
||||
virtual ~UVCSGfaceted();
|
||||
|
||||
UVCSGfaceted(const UVCSGfaceted& source);
|
||||
UVCSGfaceted& operator=(const UVCSGfaceted& source);
|
||||
|
||||
|
||||
VUSolid::EnumInside InsideNoVoxels(const UVector3& p) const;
|
||||
|
||||
virtual VUSolid::EnumInside Inside(const UVector3& p) const;
|
||||
|
||||
virtual bool Normal(const UVector3& p, UVector3& n) const;
|
||||
|
||||
double DistanceToInNoVoxels(const UVector3& p,
|
||||
const UVector3& v) const;
|
||||
|
||||
virtual double DistanceToIn(const UVector3& p,
|
||||
const UVector3& v, double aPstep = UUtils::kInfinity) const;
|
||||
|
||||
|
||||
virtual double SafetyFromOutside(const UVector3& aPoint, bool aAccurate = false) const;
|
||||
|
||||
|
||||
double DistanceTo(const UVector3& p, const bool outgoing) const;
|
||||
|
||||
double DistanceToOutNoVoxels(const UVector3& p,
|
||||
const UVector3& v,
|
||||
UVector3& n,
|
||||
bool& aConvex) const;
|
||||
|
||||
virtual double DistanceToOut(const UVector3& p,
|
||||
const UVector3& v,
|
||||
UVector3& n,
|
||||
bool& aConvex,
|
||||
double aPstep = UUtils::kInfinity) const;
|
||||
|
||||
|
||||
virtual double SafetyFromInside(const UVector3& aPoint, bool aAccurate = false) const;
|
||||
|
||||
virtual double SafetyFromInsideNoVoxels(const UVector3& aPoint, bool aAccurate = false) const;
|
||||
|
||||
virtual UGeometryType GetEntityType() const;
|
||||
|
||||
virtual std::ostream& StreamInfo(std::ostream& os) const;
|
||||
|
||||
int GetCubVolStatistics() const;
|
||||
double GetCubVolEpsilon() const;
|
||||
void SetCubVolStatistics(int st);
|
||||
void SetCubVolEpsilon(double ep);
|
||||
int GetAreaStatistics() const;
|
||||
double GetAreaAccuracy() const;
|
||||
void SetAreaStatistics(int st);
|
||||
void SetAreaAccuracy(double ep);
|
||||
|
||||
virtual double Capacity();
|
||||
// Returns an estimation of the geometrical cubic volume of the
|
||||
// solid. Caches the computed value once computed the first time.
|
||||
virtual double SurfaceArea();
|
||||
// Returns an estimation of the geometrical surface area of the
|
||||
// solid. Caches the computed value once computed the first time.
|
||||
|
||||
public: // without description
|
||||
|
||||
protected: // without description
|
||||
|
||||
double SafetyFromInsideSection(int index, const UVector3& p, UBits& bits) const;
|
||||
|
||||
inline int GetSection(double z) const
|
||||
{
|
||||
int section = UVoxelizer::BinarySearch(fZs, z);
|
||||
if (section < 0) section = 0;
|
||||
else if (section > fMaxSection) section = fMaxSection;
|
||||
return section;
|
||||
}
|
||||
|
||||
int numFace;
|
||||
UVCSGface** faces;
|
||||
double fCubicVolume;
|
||||
double fSurfaceArea;
|
||||
|
||||
|
||||
std::vector<double> fZs; // z coordinates of given sections
|
||||
std::vector<std::vector<int> > fCandidates; // precalculated candidates for each of the section
|
||||
int fMaxSection; // maximum index number of sections of the solid (i.e. their number - 1). regular polyhedra with z = 1,2,3 section has 2 sections numbered 0 and 1, therefore the fMaxSection will be 1 (that is 2 - 1 = 1)
|
||||
mutable UBox fBox; // bounding box of the polyhedra, used in some methods
|
||||
double fBoxShift; // z-shift which is added during evaluation, because bounding box center does not have to be at (0,0,0)
|
||||
bool fNoVoxels; // if set to true, no voxelized algorithms will be used
|
||||
|
||||
UVector3 GetPointOnSurfaceGeneric()const;
|
||||
// Returns a random point located on the surface of the solid
|
||||
// in case of generic Polycone or generic Polyhedra.
|
||||
|
||||
void CopyStuff(const UVCSGfaceted& source);
|
||||
void DeleteStuff();
|
||||
|
||||
void FindCandidates(double z, std::vector <int>& candidates, bool sides = false);
|
||||
|
||||
void InitVoxels(UReduciblePolygon& z, double radius);
|
||||
|
||||
private:
|
||||
|
||||
int fStatistics;
|
||||
double fCubVolEpsilon;
|
||||
double fAreaAccuracy;
|
||||
// Statistics, error accuracy for volume estimation.
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,407 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UVector2
|
||||
//
|
||||
// Class description:
|
||||
//
|
||||
// UVector2 is a general 2-vector class defining vectors in two
|
||||
// dimension using double components.
|
||||
//
|
||||
// 19.09.12 Marek Gayer
|
||||
// Created from original implementation in CLHEP
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#ifndef UVECTOR2_H
|
||||
#define UVECTOR2_H
|
||||
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
#include "UVector3.hh"
|
||||
|
||||
// Declarations of classes and global methods
|
||||
class UVector2;
|
||||
std::ostream& operator << (std::ostream&, const UVector2&);
|
||||
//std::istream & operator >> (std::istream &, UVector2 &);
|
||||
inline double operator * (const UVector2& a, const UVector2& b);
|
||||
inline UVector2 operator * (const UVector2& p, double a);
|
||||
inline UVector2 operator * (double a, const UVector2& p);
|
||||
UVector2 operator / (const UVector2& p, double a);
|
||||
inline UVector2 operator + (const UVector2& a, const UVector2& b);
|
||||
inline UVector2 operator - (const UVector2& a, const UVector2& b);
|
||||
|
||||
/**
|
||||
* @author
|
||||
* @ingroup vector
|
||||
*/
|
||||
class UVector2
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
enum { X = 0, Y = 1, NUM_COORDINATES = 2, SIZE = NUM_COORDINATES };
|
||||
// Safe indexing of the coordinates when using with matrices, arrays, etc.
|
||||
|
||||
inline UVector2(double x = 0.0, double y = 0.0);
|
||||
// The constructor.
|
||||
|
||||
inline UVector2(const UVector2& p);
|
||||
// The copy constructor.
|
||||
|
||||
explicit UVector2(const UVector3& s);
|
||||
// "demotion" constructor"
|
||||
// WARNING -- THIS IGNORES THE Z COMPONENT OF THE UVector3.
|
||||
// SO IN GENERAL, UVector2(v)==v WILL NOT HOLD!
|
||||
|
||||
inline ~UVector2();
|
||||
// The destructor.
|
||||
|
||||
// inline double x() const;
|
||||
// inline double y() const;
|
||||
// The components in cartesian coordinate system.
|
||||
|
||||
double operator()(int i) const;
|
||||
inline double operator [](int i) const;
|
||||
// Get components by index. 0-based.
|
||||
|
||||
double& operator()(int i);
|
||||
inline double& operator [](int i);
|
||||
// Set components by index. 0-based.
|
||||
|
||||
inline void setX(double x);
|
||||
inline void setY(double y);
|
||||
inline void set(double x, double y);
|
||||
// Set the components in cartesian coordinate system.
|
||||
|
||||
inline double phi() const;
|
||||
// The azimuth angle.
|
||||
|
||||
inline double mag2() const;
|
||||
// The magnitude squared.
|
||||
|
||||
inline double mag() const;
|
||||
// The magnitude.
|
||||
|
||||
inline double r() const;
|
||||
// r in polar coordinates (r, phi): equal to mag().
|
||||
|
||||
inline void setPhi(double phi);
|
||||
// Set phi keeping mag constant.
|
||||
|
||||
inline void setMag(double r);
|
||||
// Set magnitude keeping phi constant.
|
||||
|
||||
inline void setR(double r);
|
||||
// Set R keeping phi constant. Same as setMag.
|
||||
|
||||
inline void setPolar(double r, double phi);
|
||||
// Set by polar coordinates.
|
||||
|
||||
inline UVector2& operator = (const UVector2& p);
|
||||
// Assignment.
|
||||
|
||||
inline bool operator == (const UVector2& v) const;
|
||||
inline bool operator != (const UVector2& v) const;
|
||||
// Comparisons.
|
||||
|
||||
int compare(const UVector2& v) const;
|
||||
bool operator > (const UVector2& v) const;
|
||||
bool operator < (const UVector2& v) const;
|
||||
bool operator>= (const UVector2& v) const;
|
||||
bool operator<= (const UVector2& v) const;
|
||||
// dictionary ordering according to y, then x component
|
||||
|
||||
static inline double getTolerance();
|
||||
static double setTolerance(double tol);
|
||||
|
||||
double howNear(const UVector2& p) const;
|
||||
bool isNear(const UVector2& p, double epsilon = tolerance) const;
|
||||
|
||||
double howParallel(const UVector2& p) const;
|
||||
bool isParallel
|
||||
(const UVector2& p, double epsilon = tolerance) const;
|
||||
|
||||
double howOrthogonal(const UVector2& p) const;
|
||||
bool isOrthogonal
|
||||
(const UVector2& p, double epsilon = tolerance) const;
|
||||
|
||||
inline UVector2& operator += (const UVector2& p);
|
||||
// Addition.
|
||||
|
||||
inline UVector2& operator -= (const UVector2& p);
|
||||
// Subtraction.
|
||||
|
||||
inline UVector2 operator - () const;
|
||||
// Unary minus.
|
||||
|
||||
inline UVector2& operator *= (double a);
|
||||
// Scaling with real numbers.
|
||||
|
||||
inline UVector2 unit() const;
|
||||
// Unit vector parallel to this.
|
||||
|
||||
inline UVector2 orthogonal() const;
|
||||
// Vector orthogonal to this.
|
||||
|
||||
inline double dot(const UVector2& p) const;
|
||||
// Scalar product.
|
||||
|
||||
inline double angle(const UVector2&) const;
|
||||
// The angle w.r.t. another 2-vector.
|
||||
|
||||
void rotate(double);
|
||||
// Rotates the UVector2.
|
||||
|
||||
operator UVector3() const;
|
||||
// Cast a UVector2 as a UVector3.
|
||||
|
||||
// The remaining methods are friends, thus defined at global scope:
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
friend std::ostream& operator<< (std::ostream&, const UVector2&);
|
||||
// Output to a stream.
|
||||
|
||||
inline friend double operator * (const UVector2& a,
|
||||
const UVector2& b);
|
||||
// Scalar product.
|
||||
|
||||
inline friend UVector2 operator * (const UVector2& p, double a);
|
||||
// v*c
|
||||
|
||||
inline friend UVector2 operator * (double a, const UVector2& p);
|
||||
// c*v
|
||||
|
||||
friend UVector2 operator / (const UVector2& p, double a);
|
||||
// v/c
|
||||
|
||||
inline friend UVector2 operator + (const UVector2& a,
|
||||
const UVector2& b);
|
||||
// v1+v2
|
||||
|
||||
inline friend UVector2 operator - (const UVector2& a,
|
||||
const UVector2& b);
|
||||
// v1-v2
|
||||
|
||||
enum { ZMpvToleranceTicks = 100 };
|
||||
|
||||
double x;
|
||||
double y;
|
||||
// The components.
|
||||
|
||||
private:
|
||||
|
||||
static double tolerance;
|
||||
// default tolerance criterion for isNear() to return true.
|
||||
|
||||
}; // UVector2
|
||||
|
||||
static const UVector2 X_HAT2(1.0, 0.0);
|
||||
static const UVector2 Y_HAT2(0.0, 1.0);
|
||||
|
||||
|
||||
/*
|
||||
inline double UVector2::x() const {
|
||||
return x;
|
||||
}
|
||||
|
||||
inline double UVector2::y() const {
|
||||
return y;
|
||||
}
|
||||
*/
|
||||
|
||||
inline UVector2::UVector2(double x1, double y1)
|
||||
: x(x1), y(y1) {}
|
||||
|
||||
inline UVector2::UVector2(const UVector3& s)
|
||||
: x(s.x), y(s.y) {}
|
||||
|
||||
inline void UVector2::setX(double x1)
|
||||
{
|
||||
x = x1;
|
||||
}
|
||||
|
||||
inline void UVector2::setY(double y1)
|
||||
{
|
||||
y = y1;
|
||||
}
|
||||
|
||||
inline void UVector2::set(double x1, double y1)
|
||||
{
|
||||
x = x1;
|
||||
y = y1;
|
||||
}
|
||||
|
||||
double& UVector2::operator[](int i)
|
||||
{
|
||||
return operator()(i);
|
||||
}
|
||||
double UVector2::operator[](int i) const
|
||||
{
|
||||
return operator()(i);
|
||||
}
|
||||
|
||||
inline UVector2::UVector2(const UVector2& p)
|
||||
: x(p.x), y(p.y) {}
|
||||
|
||||
inline UVector2::~UVector2() {}
|
||||
|
||||
inline UVector2& UVector2::operator = (const UVector2& p)
|
||||
{
|
||||
if (this == &p) { return *this; }
|
||||
x = p.x;
|
||||
y = p.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline bool UVector2::operator == (const UVector2& v) const
|
||||
{
|
||||
return (v.x == x && v.y == y) ? true : false;
|
||||
}
|
||||
|
||||
inline bool UVector2::operator != (const UVector2& v) const
|
||||
{
|
||||
return (v.x != x || v.y != y) ? true : false;
|
||||
}
|
||||
|
||||
inline UVector2& UVector2::operator += (const UVector2& p)
|
||||
{
|
||||
x += p.x;
|
||||
y += p.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline UVector2& UVector2::operator -= (const UVector2& p)
|
||||
{
|
||||
x -= p.x;
|
||||
y -= p.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline UVector2 UVector2::operator - () const
|
||||
{
|
||||
return UVector2(-x, -y);
|
||||
}
|
||||
|
||||
inline UVector2& UVector2::operator *= (double a)
|
||||
{
|
||||
x *= a;
|
||||
y *= a;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline double UVector2::dot(const UVector2& p) const
|
||||
{
|
||||
return x * p.x + y * p.y;
|
||||
}
|
||||
|
||||
inline double UVector2::mag2() const
|
||||
{
|
||||
return x * x + y * y;
|
||||
}
|
||||
|
||||
inline double UVector2::mag() const
|
||||
{
|
||||
return std::sqrt(mag2());
|
||||
}
|
||||
|
||||
inline double UVector2::r() const
|
||||
{
|
||||
return std::sqrt(mag2());
|
||||
}
|
||||
|
||||
inline UVector2 UVector2::unit() const
|
||||
{
|
||||
double tot = mag2();
|
||||
UVector2 p(*this);
|
||||
return tot > 0.0 ? p *= (1.0 / std::sqrt(tot)) : UVector2(1, 0);
|
||||
}
|
||||
|
||||
inline UVector2 UVector2::orthogonal() const
|
||||
{
|
||||
double x1 = std::fabs(x), y1 = std::fabs(y);
|
||||
if (x1 < y1)
|
||||
{
|
||||
return UVector2(y, -x);
|
||||
}
|
||||
else
|
||||
{
|
||||
return UVector2(-y, x);
|
||||
}
|
||||
}
|
||||
|
||||
inline double UVector2::phi() const
|
||||
{
|
||||
return x == 0.0 && y == 0.0 ? 0.0 : std::atan2(y, x);
|
||||
}
|
||||
|
||||
inline double UVector2::angle(const UVector2& q) const
|
||||
{
|
||||
double ptot2 = mag2() * q.mag2();
|
||||
return ptot2 <= 0.0 ? 0.0 : std::acos(dot(q) / std::sqrt(ptot2));
|
||||
}
|
||||
|
||||
inline void UVector2::setMag(double r1)
|
||||
{
|
||||
double ph = phi();
|
||||
setX(r1 * std::cos(ph));
|
||||
setY(r1 * std::sin(ph));
|
||||
}
|
||||
|
||||
inline void UVector2::setR(double r1)
|
||||
{
|
||||
setMag(r1);
|
||||
}
|
||||
|
||||
inline void UVector2::setPhi(double phi1)
|
||||
{
|
||||
double ma = mag();
|
||||
setX(ma * std::cos(phi1));
|
||||
setY(ma * std::sin(phi1));
|
||||
}
|
||||
|
||||
inline void UVector2::setPolar(double r1, double phi1)
|
||||
{
|
||||
setX(r1 * std::cos(phi1));
|
||||
setY(r1 * std::sin(phi1));
|
||||
}
|
||||
|
||||
inline UVector2 operator + (const UVector2& a, const UVector2& b)
|
||||
{
|
||||
return UVector2(a.x + b.x, a.y + b.y);
|
||||
}
|
||||
|
||||
inline UVector2 operator - (const UVector2& a, const UVector2& b)
|
||||
{
|
||||
return UVector2(a.x - b.x, a.y - b.y);
|
||||
}
|
||||
|
||||
inline UVector2 operator * (const UVector2& p, double a)
|
||||
{
|
||||
return UVector2(a * p.x, a * p.y);
|
||||
}
|
||||
|
||||
inline UVector2 operator * (double a, const UVector2& p)
|
||||
{
|
||||
return UVector2(a * p.x, a * p.y);
|
||||
}
|
||||
|
||||
inline double operator * (const UVector2& a, const UVector2& b)
|
||||
{
|
||||
return a.dot(b);
|
||||
}
|
||||
|
||||
inline double UVector2::getTolerance()
|
||||
{
|
||||
return tolerance;
|
||||
}
|
||||
|
||||
|
||||
#endif /* UVECTOR2_H */
|
||||
@@ -0,0 +1,180 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UVector2.icc
|
||||
//
|
||||
// Implementation of inline methods of UVector2
|
||||
//
|
||||
// 19.10.12 Marek Gayer
|
||||
// Created from original implementation in CLHEP
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace CLHEP {
|
||||
|
||||
inline double Hep2Vector::x() const {
|
||||
return dx;
|
||||
}
|
||||
|
||||
inline double Hep2Vector::y() const {
|
||||
return dy;
|
||||
}
|
||||
|
||||
inline Hep2Vector::Hep2Vector(double x1, double y1)
|
||||
: dx(x1), dy(y1) {}
|
||||
|
||||
inline Hep2Vector::Hep2Vector( const Hep3Vector & s)
|
||||
: dx(s.x()), dy(s.y()) {}
|
||||
|
||||
inline void Hep2Vector::setX(double x1) {
|
||||
dx = x1;
|
||||
}
|
||||
|
||||
inline void Hep2Vector::setY(double y1) {
|
||||
dy = y1;
|
||||
}
|
||||
|
||||
inline void Hep2Vector::set(double x1, double y1) {
|
||||
dx = x1;
|
||||
dy = y1;
|
||||
}
|
||||
|
||||
double & Hep2Vector::operator[] (int i) { return operator()(i); }
|
||||
double Hep2Vector::operator[] (int i) const { return operator()(i); }
|
||||
|
||||
inline Hep2Vector::Hep2Vector(const Hep2Vector & p)
|
||||
: dx(p.x()), dy(p.y()) {}
|
||||
|
||||
inline Hep2Vector::~Hep2Vector() {}
|
||||
|
||||
inline Hep2Vector & Hep2Vector::operator = (const Hep2Vector & p) {
|
||||
dx = p.x();
|
||||
dy = p.y();
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline bool Hep2Vector::operator == (const Hep2Vector& v) const {
|
||||
return (v.x()==x() && v.y()==y()) ? true : false;
|
||||
}
|
||||
|
||||
inline bool Hep2Vector::operator != (const Hep2Vector& v) const {
|
||||
return (v.x()!=x() || v.y()!=y()) ? true : false;
|
||||
}
|
||||
|
||||
inline Hep2Vector& Hep2Vector::operator += (const Hep2Vector & p) {
|
||||
dx += p.x();
|
||||
dy += p.y();
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Hep2Vector& Hep2Vector::operator -= (const Hep2Vector & p) {
|
||||
dx -= p.x();
|
||||
dy -= p.y();
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Hep2Vector Hep2Vector::operator - () const {
|
||||
return Hep2Vector(-dx, -dy);
|
||||
}
|
||||
|
||||
inline Hep2Vector& Hep2Vector::operator *= (double a) {
|
||||
dx *= a;
|
||||
dy *= a;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline double Hep2Vector::dot(const Hep2Vector & p) const {
|
||||
return dx*p.x() + dy*p.y();
|
||||
}
|
||||
|
||||
inline double Hep2Vector::mag2() const {
|
||||
return dx*dx + dy*dy;
|
||||
}
|
||||
|
||||
inline double Hep2Vector::mag() const {
|
||||
return std::sqrt(mag2());
|
||||
}
|
||||
|
||||
inline double Hep2Vector::r() const {
|
||||
return std::sqrt(mag2());
|
||||
}
|
||||
|
||||
inline Hep2Vector Hep2Vector::unit() const {
|
||||
double tot = mag2();
|
||||
Hep2Vector p(*this);
|
||||
return tot > 0.0 ? p *= (1.0/std::sqrt(tot)) : Hep2Vector(1,0);
|
||||
}
|
||||
|
||||
inline Hep2Vector Hep2Vector::orthogonal() const {
|
||||
double x1 = std::fabs(dx), y1 = std::fabs(dy);
|
||||
if (x1 < y1) {
|
||||
return Hep2Vector(dy,-dx);
|
||||
}else{
|
||||
return Hep2Vector(-dy,dx);
|
||||
}
|
||||
}
|
||||
|
||||
inline double Hep2Vector::phi() const {
|
||||
return dx == 0.0 && dy == 0.0 ? 0.0 : std::atan2(dy,dx);
|
||||
}
|
||||
|
||||
inline double Hep2Vector::angle(const Hep2Vector & q) const {
|
||||
double ptot2 = mag2()*q.mag2();
|
||||
return ptot2 <= 0.0 ? 0.0 : std::acos(dot(q)/std::sqrt(ptot2));
|
||||
}
|
||||
|
||||
inline void Hep2Vector::setMag(double r1){
|
||||
double ph = phi();
|
||||
setX( r1 * std::cos(ph) );
|
||||
setY( r1 * std::sin(ph) );
|
||||
}
|
||||
|
||||
inline void Hep2Vector::setR(double r1){
|
||||
setMag(r1);
|
||||
}
|
||||
|
||||
inline void Hep2Vector::setPhi(double phi1){
|
||||
double ma = mag();
|
||||
setX( ma * std::cos(phi1) );
|
||||
setY( ma * std::sin(phi1) );
|
||||
}
|
||||
|
||||
inline void Hep2Vector::setPolar(double r1, double phi1){
|
||||
setX( r1 * std::cos(phi1) );
|
||||
setY( r1 * std::sin(phi1) );
|
||||
}
|
||||
|
||||
inline Hep2Vector operator + (const Hep2Vector & a, const Hep2Vector & b) {
|
||||
return Hep2Vector(a.x() + b.x(), a.y() + b.y());
|
||||
}
|
||||
|
||||
inline Hep2Vector operator - (const Hep2Vector & a, const Hep2Vector & b) {
|
||||
return Hep2Vector(a.x() - b.x(), a.y() - b.y());
|
||||
}
|
||||
|
||||
inline Hep2Vector operator * (const Hep2Vector & p, double a) {
|
||||
return Hep2Vector(a*p.x(), a*p.y());
|
||||
}
|
||||
|
||||
inline Hep2Vector operator * (double a, const Hep2Vector & p) {
|
||||
return Hep2Vector(a*p.x(), a*p.y());
|
||||
}
|
||||
|
||||
inline double operator * (const Hep2Vector & a, const Hep2Vector & b) {
|
||||
return a.dot(b);
|
||||
}
|
||||
|
||||
inline double Hep2Vector::getTolerance () {
|
||||
return tolerance;
|
||||
}
|
||||
|
||||
} // namespace CLHEP
|
||||
|
||||
@@ -0,0 +1,329 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UVector3
|
||||
//
|
||||
// Class description:
|
||||
//
|
||||
// Bucket type for Vector type.
|
||||
//
|
||||
// 19.09.12 Marek Gayer
|
||||
// Created from original implementation in CLHEP
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#ifndef USOLIDS_UVector3
|
||||
#define USOLIDS_UVector3
|
||||
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
struct UVector3
|
||||
{
|
||||
public:
|
||||
UVector3()
|
||||
{
|
||||
x = y = z = 0.0;
|
||||
}
|
||||
UVector3(double xval, double yval, double zval)
|
||||
{
|
||||
x = xval;
|
||||
y = yval;
|
||||
z = zval;
|
||||
}
|
||||
UVector3(double theta, double phi);
|
||||
UVector3(const double coord[3])
|
||||
{
|
||||
x = coord[0];
|
||||
y = coord[1];
|
||||
z = coord[2];
|
||||
}
|
||||
|
||||
inline UVector3& operator = (const UVector3& v);
|
||||
inline UVector3& operator = (const double* vect);
|
||||
// Assignments
|
||||
|
||||
inline bool operator == (const UVector3&) const;
|
||||
inline bool operator != (const UVector3&) const;
|
||||
// Comparisons.
|
||||
|
||||
inline UVector3 operator - () const;
|
||||
// Unary minus.
|
||||
|
||||
inline UVector3& operator += (const UVector3&);
|
||||
// Addition.
|
||||
|
||||
inline UVector3& operator -= (const UVector3&);
|
||||
// Subtraction.
|
||||
|
||||
inline double& operator[](int index);
|
||||
|
||||
inline double operator[](int index) const;
|
||||
|
||||
inline UVector3& operator *= (double);
|
||||
// Scaling with real numbers.
|
||||
|
||||
inline UVector3& operator /= (double);
|
||||
// Dividing with real numbers.
|
||||
|
||||
inline double Dot(const UVector3&) const;
|
||||
// Scalar product.
|
||||
|
||||
inline UVector3 Cross(const UVector3&) const;
|
||||
// Cross product.
|
||||
|
||||
double Angle(const UVector3&) const;
|
||||
// The angle w.r.t. another 3-vector.
|
||||
|
||||
UVector3 Unit() const;
|
||||
// Unit vector parallel to this.
|
||||
|
||||
inline bool IsNull() const;
|
||||
// Check if vector is null
|
||||
|
||||
inline void SetNull();
|
||||
// Set all components to 0.
|
||||
|
||||
inline void Set(double xx, double yy, double zz);
|
||||
// Assign values to components
|
||||
|
||||
inline void Set(double xx);
|
||||
// Assign value to all components
|
||||
|
||||
double Normalize();
|
||||
// Normalize to unit this vector
|
||||
|
||||
double Phi() const;
|
||||
// The azimuth angle. returns phi from -pi to pi
|
||||
|
||||
double Theta() const;
|
||||
// The polar angle.
|
||||
|
||||
inline double CosTheta() const;
|
||||
// Cosine of the polar angle.
|
||||
|
||||
inline double Mag2() const;
|
||||
// The magnitude squared (rho^2 in spherical coordinate system).
|
||||
|
||||
double Mag() const;
|
||||
// The magnitude (rho in spherical coordinate system).
|
||||
|
||||
double Perp2() const;
|
||||
// The transverse component (R^2 in cylindrical coordinate system).
|
||||
|
||||
double Perp() const;
|
||||
// The transverse component (R in cylindrical coordinate system).
|
||||
|
||||
void RotateX(double);
|
||||
// Rotates the vector around the x-axis.
|
||||
|
||||
void RotateY(double);
|
||||
// Rotates the vector around the y-axis.
|
||||
|
||||
void RotateZ(double);
|
||||
// Rotates the vector around the z-axis.
|
||||
|
||||
inline UVector3& MultiplyByComponents(const UVector3& p);
|
||||
|
||||
public:
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
};
|
||||
|
||||
UVector3 operator + (const UVector3&, const UVector3&);
|
||||
// Addition of 3-vectors.
|
||||
|
||||
UVector3 operator - (const UVector3&, const UVector3&);
|
||||
// Subtraction of 3-vectors.
|
||||
|
||||
double operator * (const UVector3&, const UVector3&);
|
||||
// Scalar product of 3-vectors.
|
||||
|
||||
UVector3 operator * (const UVector3&, double a);
|
||||
UVector3 operator / (const UVector3&, double a);
|
||||
UVector3 operator * (double a, const UVector3&);
|
||||
|
||||
// Scaling of 3-vectors with a real number
|
||||
|
||||
//______________________________________________________________________________
|
||||
inline UVector3& UVector3::MultiplyByComponents(const UVector3& p)
|
||||
{
|
||||
// Assignment of a UVector3
|
||||
x *= p.x;
|
||||
y *= p.y;
|
||||
z *= p.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
inline UVector3& UVector3::operator = (const UVector3& p)
|
||||
{
|
||||
// Assignment of a UVector3
|
||||
if (this == &p) { return *this; }
|
||||
x = p.x;
|
||||
y = p.y;
|
||||
z = p.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline UVector3& UVector3::operator = (const double vect[3])
|
||||
{
|
||||
// Assignment of a C array
|
||||
x = vect[0];
|
||||
y = vect[1];
|
||||
z = vect[2];
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline bool UVector3::operator == (const UVector3& v) const
|
||||
{
|
||||
return (v.x == x && v.y == y && v.z == z) ? true : false;
|
||||
}
|
||||
|
||||
inline bool UVector3::operator != (const UVector3& v) const
|
||||
{
|
||||
return (v.x != x || v.y != y || v.z != z) ? true : false;
|
||||
}
|
||||
|
||||
inline UVector3& UVector3::operator += (const UVector3& p)
|
||||
{
|
||||
x += p.x;
|
||||
y += p.y;
|
||||
z += p.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline UVector3& UVector3::operator -= (const UVector3& p)
|
||||
{
|
||||
x -= p.x;
|
||||
y -= p.y;
|
||||
z -= p.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline UVector3 UVector3::operator - () const
|
||||
{
|
||||
return UVector3(-x, -y, -z);
|
||||
}
|
||||
|
||||
inline UVector3& UVector3::operator *= (double a)
|
||||
{
|
||||
x *= a;
|
||||
y *= a;
|
||||
z *= a;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline UVector3& UVector3::operator /= (double a)
|
||||
{
|
||||
a = 1. / a;
|
||||
x *= a;
|
||||
y *= a;
|
||||
z *= a;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline bool UVector3::IsNull() const
|
||||
{
|
||||
return ((std::abs(x) + std::abs(y) + std::abs(z)) == 0.0) ? true : false;
|
||||
}
|
||||
|
||||
/*
|
||||
inline void UVector3::SetNull() {
|
||||
x = y = z = 0.0;
|
||||
}
|
||||
*/
|
||||
|
||||
inline void UVector3::Set(double xx, double yy, double zz)
|
||||
{
|
||||
x = xx;
|
||||
y = yy;
|
||||
z = zz;
|
||||
}
|
||||
|
||||
inline void UVector3::Set(double xx)
|
||||
{
|
||||
x = y = z = xx;
|
||||
}
|
||||
|
||||
inline double UVector3::Dot(const UVector3& p) const
|
||||
{
|
||||
return x * p.x + y * p.y + z * p.z;
|
||||
}
|
||||
|
||||
inline UVector3 UVector3::Cross(const UVector3& p) const
|
||||
{
|
||||
return UVector3(y * p.z - p.y * z, z * p.x - p.z * x, x * p.y - p.x * y);
|
||||
}
|
||||
|
||||
inline double UVector3::Mag2() const
|
||||
{
|
||||
return x * x + y * y + z * z;
|
||||
}
|
||||
|
||||
inline double UVector3::Perp2() const
|
||||
{
|
||||
return x * x + y * y;
|
||||
}
|
||||
|
||||
inline double UVector3::CosTheta() const
|
||||
{
|
||||
double ptot = Mag();
|
||||
return ptot == 0.0 ? 1.0 : z / ptot;
|
||||
}
|
||||
|
||||
|
||||
inline double& UVector3::operator[](int index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
return x;
|
||||
case 1:
|
||||
return y;
|
||||
case 2:
|
||||
return z;
|
||||
default:
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
inline double UVector3::operator[](int index) const
|
||||
{
|
||||
// return operator()(index);
|
||||
|
||||
// TODO: test performance of both versions on Linux
|
||||
// => first version is slightly faster
|
||||
if (true)
|
||||
{
|
||||
double vec[3] = {x, y, z};
|
||||
return vec[index];
|
||||
}
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
return x;
|
||||
case 1:
|
||||
return y;
|
||||
case 2:
|
||||
return z;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline std::ostream& operator<< (std::ostream& os, const UVector3& v)
|
||||
{
|
||||
return os << "(" << v.x << "," << v.y << "," << v.z << ")";
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,348 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UVoxelizer
|
||||
//
|
||||
// Class description:
|
||||
//
|
||||
// Voxelizer used for UPolycone, UPolyhedra, UTessellatedSolid
|
||||
// and UMultiUnion.
|
||||
//
|
||||
// 19.10.12 Marek Gayer
|
||||
// Created from original implementation in ROOT
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#ifndef UVoxelizer_HH
|
||||
#define UVoxelizer_HH
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include "UBits.hh"
|
||||
#include "UBox.hh"
|
||||
#include "VUFacet.hh"
|
||||
#include "VUSolid.hh"
|
||||
#include "UUtils.hh"
|
||||
#include "UTransform3D.hh"
|
||||
|
||||
struct UVoxelBox
|
||||
{
|
||||
UVector3 hlen; // half length of the box
|
||||
UVector3 pos; // position of the box
|
||||
};
|
||||
|
||||
struct UVoxelInfo
|
||||
{
|
||||
int count;
|
||||
int previous;
|
||||
int next;
|
||||
};
|
||||
|
||||
class UVoxelizer
|
||||
{
|
||||
// friend class UVoxelCandidatesIterator;
|
||||
|
||||
public:
|
||||
|
||||
template <typename T>
|
||||
|
||||
// Binary search
|
||||
static inline int BinarySearch(const std::vector<T>& vec, T value)
|
||||
{
|
||||
// Binary search in an array of doubles. If match is found, function returns
|
||||
// position of element. If no match found, function gives nearest
|
||||
// element smaller than value.
|
||||
typename std::vector<T>::const_iterator begin = vec.begin(), end = vec.end();
|
||||
int res = std::upper_bound(begin, end, value) - begin - 1;
|
||||
return res;
|
||||
}
|
||||
// int BinarySearch(int n, const T *array, T value);
|
||||
|
||||
#ifdef USOLIDSONLY
|
||||
void Voxelize(std::vector<VUSolid*>& solids, std::vector<UTransform3D*>& transforms);
|
||||
#endif // USOLIDSONLY
|
||||
|
||||
void Voxelize(std::vector<VUFacet*>& facets);
|
||||
|
||||
void DisplayVoxelLimits();
|
||||
void DisplayBoundaries();
|
||||
void DisplayListNodes();
|
||||
|
||||
UVoxelizer();
|
||||
~UVoxelizer();
|
||||
|
||||
// Method displaying the nodes located in a voxel characterized by its three indexes:
|
||||
void GetCandidatesVoxel(std::vector<int>& voxels);
|
||||
// Method returning in a vector container the nodes located in a voxel characterized by its three indexes:
|
||||
int GetCandidatesVoxelArray(const UVector3& point, std::vector<int>& list, UBits* crossed = NULL) const;
|
||||
|
||||
int GetCandidatesVoxelArray(const std::vector<int>& voxels, const UBits bitmasks[], std::vector<int>& list, UBits* crossed = NULL) const;
|
||||
|
||||
int GetCandidatesVoxelArray(const std::vector<int>& voxels, std::vector<int>& list, UBits* crossed = NULL)const;
|
||||
|
||||
// Method returning the pointer to the array containing the characteristics of each box:
|
||||
inline const std::vector<UVoxelBox>& GetBoxes() const
|
||||
{
|
||||
return fBoxes;
|
||||
}
|
||||
inline const std::vector<double>& GetBoundary(int index) const
|
||||
{
|
||||
return fBoundaries[index];
|
||||
}
|
||||
|
||||
bool UpdateCurrentVoxel(const UVector3& point, const UVector3& direction, std::vector<int>& curVoxel) const;
|
||||
|
||||
inline void GetVoxel(std::vector<int>& curVoxel, const UVector3& point) const
|
||||
{
|
||||
for (int i = 0; i <= 2; ++i)
|
||||
{
|
||||
const std::vector<double>& boundary = GetBoundary(i);
|
||||
int n = BinarySearch(boundary, point[i]);
|
||||
if (n == -1) n = 0;
|
||||
else if (n == (int) boundary.size() - 1) n--;
|
||||
curVoxel[i] = n;
|
||||
}
|
||||
}
|
||||
|
||||
inline int GetBitsPerSlice() const
|
||||
{
|
||||
return fNPerSlice * 8 * sizeof(unsigned int);
|
||||
}
|
||||
|
||||
bool Contains(const UVector3& point) const;
|
||||
|
||||
double DistanceToNext(const UVector3& point, const UVector3& direction, std::vector<int>& curVoxel) const;
|
||||
|
||||
double DistanceToFirst(const UVector3& point, const UVector3& direction) const;
|
||||
|
||||
double SafetyToBoundingBox(const UVector3& point) const;
|
||||
|
||||
inline int GetVoxelsIndex(int x, int y, int z) const
|
||||
{
|
||||
if (x < 0 || y < 0 || z < 0) return -1;
|
||||
int maxX = fBoundaries[0].size();
|
||||
int maxY = fBoundaries[1].size();
|
||||
int index = x + y * maxX + z * maxX * maxY;
|
||||
return index;
|
||||
}
|
||||
|
||||
inline int GetVoxelsIndex(const std::vector<int>& voxels) const
|
||||
{
|
||||
return GetVoxelsIndex(voxels[0], voxels[1], voxels[2]);
|
||||
}
|
||||
|
||||
inline bool GetPointVoxel(const UVector3& p, std::vector<int>& voxels) const
|
||||
{
|
||||
for (int i = 0; i <= 2; ++i)
|
||||
if (p[i] < *fBoundaries[i].begin() || p[i] > *fBoundaries[i].end()) return false;
|
||||
|
||||
for (int i = 0; i <= 2; ++i)
|
||||
voxels[i] = BinarySearch(fBoundaries[i], p[i]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline int GetPointIndex(const UVector3& p) const
|
||||
{
|
||||
int maxX = fBoundaries[0].size();
|
||||
int maxY = fBoundaries[1].size();
|
||||
int x = BinarySearch(fBoundaries[0], p[0]);
|
||||
int y = BinarySearch(fBoundaries[1], p[1]);
|
||||
int z = BinarySearch(fBoundaries[2], p[2]);
|
||||
int index = x + y * maxX + z * maxX * maxY;
|
||||
return index;
|
||||
}
|
||||
|
||||
inline const UBits& Empty() const
|
||||
{
|
||||
return fEmpty;
|
||||
}
|
||||
|
||||
inline bool IsEmpty(int index) const
|
||||
{
|
||||
return fEmpty[index];
|
||||
}
|
||||
|
||||
void SetMaxVoxels(int max);
|
||||
|
||||
void SetMaxVoxels(const UVector3& reductionRatio);
|
||||
|
||||
inline int GetMaxVoxels(UVector3& ratioOfReduction)
|
||||
{
|
||||
ratioOfReduction = fReductionRatio;
|
||||
return fMaxVoxels;
|
||||
}
|
||||
|
||||
int AllocatedMemory();
|
||||
|
||||
inline long long GetCountOfVoxels() const
|
||||
{
|
||||
return fCountOfVoxels;
|
||||
}
|
||||
|
||||
inline long long CountVoxels(std::vector<double> boundaries[]) const
|
||||
{
|
||||
long long sx = boundaries[0].size() - 1;
|
||||
long long sy = boundaries[1].size() - 1;
|
||||
long long sz = boundaries[2].size() - 1;
|
||||
return sx * sy * sz;
|
||||
}
|
||||
|
||||
/*
|
||||
inline int GetCandidates(std::vector<int> &curVoxel, std::vector<int> *&candidates, std::vector<int> &space) const
|
||||
{
|
||||
int voxelsIndex;
|
||||
int emptys = fEmpty.GetNbits();
|
||||
if (!emptys || ((voxelsIndex = GetVoxelsIndex(curVoxel)) >= 0) && !fEmpty[voxelsIndex])
|
||||
{
|
||||
if (emptys)
|
||||
{
|
||||
candidates = &fCandidates[voxelsIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
GetCandidatesVoxelArray(curVoxel, space, NULL);
|
||||
candidates = &space;
|
||||
}
|
||||
return candidates->size();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
inline const std::vector<int>& GetCandidates(std::vector<int>& curVoxel) const
|
||||
{
|
||||
int voxelsIndex = GetVoxelsIndex(curVoxel);
|
||||
if (voxelsIndex >= 0 && !fEmpty[voxelsIndex])
|
||||
{
|
||||
return fCandidates[voxelsIndex];
|
||||
}
|
||||
return fNoCandidates;
|
||||
}
|
||||
|
||||
inline int GetVoxelBoxesSize() const
|
||||
{
|
||||
return fVoxelBoxes.size();
|
||||
}
|
||||
|
||||
inline const UVoxelBox& GetVoxelBox(int i) const
|
||||
{
|
||||
return fVoxelBoxes[i];
|
||||
}
|
||||
|
||||
inline const std::vector<int>& GetVoxelBoxCandidates(int i) const
|
||||
{
|
||||
return fVoxelBoxesCandidates[i];
|
||||
}
|
||||
|
||||
inline int GetTotalCandidates() const
|
||||
{
|
||||
return fTotalCandidates;
|
||||
}
|
||||
|
||||
static double MinDistanceToBox(const UVector3& aPoint, const UVector3& f);
|
||||
|
||||
static void SetDefaultVoxelsCount(int count);
|
||||
|
||||
static int GetDefaultVoxelsCount();
|
||||
|
||||
void BuildBoundingBox();
|
||||
|
||||
void BuildBoundingBox(UVector3& amin, UVector3& amax, double tolerance = 0);
|
||||
|
||||
private:
|
||||
|
||||
static int fDefaultVoxelsCount;
|
||||
|
||||
std::vector<UVoxelBox> fVoxelBoxes;
|
||||
|
||||
std::vector<std::vector<int> > fVoxelBoxesCandidates;
|
||||
|
||||
mutable std::map<int, std::vector<int> > fCandidates;
|
||||
|
||||
const std::vector<int> fNoCandidates;
|
||||
|
||||
long long fCountOfVoxels;
|
||||
|
||||
void BuildEmpty();
|
||||
|
||||
std::string GetCandidatesAsString(const UBits& bits);
|
||||
|
||||
void CreateSortedBoundary(std::vector<double>& boundaryRaw, int axis);
|
||||
|
||||
void BuildBoundaries();
|
||||
|
||||
void BuildReduceVoxels(std::vector<double> fBoundaries[], UVector3 reductionRatio);
|
||||
|
||||
void BuildReduceVoxels2(std::vector<double> fBoundaries[], UVector3 reductionRatio);
|
||||
|
||||
#ifdef USOLIDSONLY
|
||||
void BuildVoxelLimits(std::vector<VUSolid*>& solids, std::vector<UTransform3D*>& transforms);
|
||||
#endif // USOLIDSONLY
|
||||
|
||||
void BuildVoxelLimits(std::vector<VUFacet*>& facets);
|
||||
|
||||
void DisplayBoundaries(std::vector<double>& fBoundaries);
|
||||
|
||||
void BuildBitmasks(std::vector<double> fBoundaries[], UBits bitmasks[]);
|
||||
|
||||
void SetReductionRatio(int maxVoxels, UVector3& reductionRatio);
|
||||
|
||||
void CreateMiniVoxels(std::vector<double> fBoundaries[], UBits bitmasks[]);
|
||||
|
||||
int fNPerSlice;
|
||||
|
||||
std::vector<UVoxelBox> fBoxes; // Array of box limits on the 3 cartesian axis
|
||||
|
||||
std::vector<double> fBoundaries[3]; // Sorted and if need skimmed fBoundaries along X,Y,Z axis
|
||||
|
||||
std::vector<int> fCandidatesCounts[3];
|
||||
|
||||
int fTotalCandidates;
|
||||
|
||||
UBits fBitmasks[3];
|
||||
|
||||
UVector3 fBoundingBoxCenter;
|
||||
UBox fBoundingBox;
|
||||
UVector3 fBoundingBoxSize;
|
||||
|
||||
UVector3 fReductionRatio;
|
||||
|
||||
int fMaxVoxels;
|
||||
|
||||
double fTolerance;
|
||||
|
||||
UBits fEmpty;
|
||||
};
|
||||
|
||||
|
||||
#ifdef USOLIDSONLY
|
||||
|
||||
/*
|
||||
class UVoxelCandidatesIterator
|
||||
{
|
||||
private:
|
||||
unsigned int mask;
|
||||
int curInt, curBit, carNodes, n, sliceX, sliceY, sliceZ;
|
||||
unsigned int *maskX, *maskY, *maskZ;
|
||||
unsigned int *maskXLeft, *maskYLeft, *maskZLeft;
|
||||
bool nextAvailable;
|
||||
|
||||
public:
|
||||
UVoxelCandidatesIterator(const UVoxelizer &f, const UVector3 &point);
|
||||
|
||||
int Next();
|
||||
};
|
||||
*/
|
||||
|
||||
#endif // USOLIDSONLY
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,92 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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 and of QinetiQ Ltd, *
|
||||
// * subject to DEFCON 705 IPR conditions. *
|
||||
// * 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: UFacet.hh,v 1.8 2010-09-23 10:27:25 gcosmo Exp $
|
||||
// GEANT4 tag $Name: not supported by cvs2svn $
|
||||
//
|
||||
// Author: Marek Gayer, started from original implementation by P R Truscott, 2004
|
||||
//
|
||||
////
|
||||
// Class description:
|
||||
//
|
||||
// Base class defining the facets which are components of a
|
||||
// G4TessellatedSolid shape.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef UFacet_hh
|
||||
#define UFacet_hh
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "UVector3.hh"
|
||||
#include "UTypes.hh"
|
||||
|
||||
enum UFacetVertexType {UABSOLUTE, URELATIVE};
|
||||
|
||||
class UTessellatedSolid;
|
||||
|
||||
class VUFacet
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~VUFacet () {};
|
||||
|
||||
virtual int GetNumberOfVertices () const = 0;
|
||||
virtual UVector3 GetVertex (int i) const = 0;
|
||||
virtual void SetVertex (int i, const UVector3 &val) = 0;
|
||||
virtual UGeometryType GetEntityType () const = 0;
|
||||
virtual UVector3 GetSurfaceNormal () const = 0;
|
||||
virtual bool IsDefined () const = 0;
|
||||
virtual UVector3 GetCircumcentre () const = 0;
|
||||
virtual double GetRadius () const = 0;
|
||||
virtual VUFacet *GetClone () = 0;
|
||||
virtual double Distance (const UVector3&, const double) = 0;
|
||||
virtual double Distance (const UVector3&, const double, const bool) = 0;
|
||||
virtual double Extent (const UVector3) = 0;
|
||||
virtual bool Intersect (const UVector3&, const UVector3 &, const bool , double &, double &, UVector3 &) = 0;
|
||||
virtual double GetArea() = 0;
|
||||
virtual UVector3 GetPointOnFace() const = 0;
|
||||
|
||||
bool operator== (const VUFacet &right) const;
|
||||
void ApplyTranslation (const UVector3 v);
|
||||
std::ostream &StreamInfo(std::ostream &os) const;
|
||||
bool IsInside(const UVector3 &p) const;
|
||||
|
||||
virtual int AllocatedMemory() = 0;
|
||||
virtual void SetVertexIndex (const int i, const int j) = 0;
|
||||
virtual int GetVertexIndex (const int i) const = 0;
|
||||
|
||||
virtual void SetVertices(std::vector<UVector3> *vertices) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
static const double dirTolerance;
|
||||
static const double kCarTolerance;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,156 @@
|
||||
#ifndef USOLIDS_VUSolid
|
||||
#define USOLIDS_VUSolid
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// "Universal" Solid Interface
|
||||
// Authors: J. Apostolakis, G. Cosmo, M. Gayer, A. Gheata, A. Munnich, T. Nikitina (CERN)
|
||||
//
|
||||
// Created: 25 May 2011
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "UTypes.hh"
|
||||
#include "UVector3.hh"
|
||||
|
||||
#include "UUtils.hh"
|
||||
|
||||
#define USOLIDS
|
||||
#define USOLIDSONLY
|
||||
|
||||
class VUSolid
|
||||
{
|
||||
public:
|
||||
|
||||
enum EnumInside { eInside=0, eSurface=1, eOutside=2 };
|
||||
// Use eInside < eSurface < eOutside: allows "max(,)" to combine Inside of surfaces
|
||||
// Potentially replace eSurface with eInSurface, eOutSurface
|
||||
|
||||
enum EAxisType { eXaxis=0, eYaxis=1, eZaxis=2};
|
||||
|
||||
protected:
|
||||
static double fgTolerance;
|
||||
static double frTolerance;
|
||||
static double faTolerance;
|
||||
|
||||
// =>10 degrees/wedge for complete tube
|
||||
|
||||
public:
|
||||
VUSolid();
|
||||
VUSolid(const std::string &name);
|
||||
virtual ~VUSolid();
|
||||
|
||||
// Accessors and modifiers for Tolerance
|
||||
inline double GetCarTolerance() const;
|
||||
inline double GetRadTolerance() const;
|
||||
inline double GetAngTolerance() const;
|
||||
void SetCarTolerance(double eps);
|
||||
void SetRadTolerance(double eps);
|
||||
void SetAngTolerance(double eps);
|
||||
|
||||
// Navigation methods
|
||||
virtual EnumInside Inside (const UVector3 &aPoint) const = 0;
|
||||
//
|
||||
// Evaluate if point is inside, outside or on the surface within the tolerance
|
||||
virtual double SafetyFromInside ( const UVector3 &aPoint,
|
||||
bool aAccurate=false) const = 0;
|
||||
virtual double SafetyFromOutside( const UVector3 &aPoint,
|
||||
bool aAccurate=false) const = 0;
|
||||
//
|
||||
// Estimates isotropic distance to the surface of the solid. This must
|
||||
// be either accurate or an underestimate.
|
||||
// Two modes: - default/fast mode, sacrificing accuracy for speed
|
||||
// - "precise" mode, requests accurate value if available.
|
||||
// For both modes, if at a large distance from solid ( > ? )
|
||||
// it is expected that a simplified calculation will be made if available.
|
||||
|
||||
virtual double DistanceToIn( const UVector3 &aPoint,
|
||||
const UVector3 &aDirection,
|
||||
double aPstep = UUtils::kInfinity) const = 0;
|
||||
virtual double DistanceToOut( const UVector3 &aPoint,
|
||||
const UVector3 &aDirection,
|
||||
UVector3 &aNormalVector,
|
||||
bool &aConvex,
|
||||
double aPstep = UUtils::kInfinity) const = 0;
|
||||
//
|
||||
// o return the exact distance (double) from a surface, given a direction
|
||||
// o compute the normal on the surface, returned as argument, calculated
|
||||
// within the method to verify if it is close to the surface or not
|
||||
// o for DistanceToOut(), normal-vector and convexity flag could be optional (to decide).
|
||||
// If normal cannot be computed (or shape is not convex), set 'convex' to 'false'.
|
||||
// o for DistanceToIn(), the normal-vector could be added as optional
|
||||
|
||||
virtual bool Normal( const UVector3& aPoint, UVector3 &aNormal ) const = 0;
|
||||
// Computes the normal on a surface and returns it as a unit vector
|
||||
// In case a point is further than tolerance_normal from a surface, set validNormal=false
|
||||
// Must return a valid vector. (even if the point is not on the surface.)
|
||||
//
|
||||
// On an edge or corner, provide an average normal of all facets within tolerance
|
||||
|
||||
// Decision: provide or not the Boolean 'validNormal' argument for returning validity
|
||||
|
||||
virtual void ExtentAxis(EAxisType aAxis, double &aMin, double &aMax) const;
|
||||
|
||||
virtual void Extent( UVector3 &aMin, UVector3 &aMax ) const = 0;
|
||||
// Return the minimum and maximum extent along all Cartesian axes
|
||||
// For both the Extent methods
|
||||
// o Expect mostly to use a GetBBox()/CalculateBBox() method internally to compute the extent
|
||||
// o Decision: whether to store the computed BBox (containing or representing 6 double values),
|
||||
// and whether to compute it at construction time.
|
||||
// Methods are *not* const to allow caching of the Bounding Box
|
||||
virtual UGeometryType GetEntityType() const = 0;
|
||||
// Provide identification of the class of an object.
|
||||
// (required for persistency and STEP interface)
|
||||
|
||||
const std::string &GetName() const {return fName;}
|
||||
void SetName(const std::string &aName) {fName = aName;}
|
||||
|
||||
// Auxiliary methods
|
||||
virtual double Capacity() = 0 ; // like CubicVolume()
|
||||
virtual double SurfaceArea() = 0 ;
|
||||
// Expect the solids to cache the values of Capacity and Surface Area
|
||||
|
||||
// Sampling
|
||||
virtual void SamplePointsInside(int /*aNpoints*/, UVector3 * /*aArray*/) const {}
|
||||
virtual void SamplePointsOnSurface(int /*aNpoints*/, UVector3 * /*aArray*/) const {}
|
||||
virtual void SamplePointsOnEdge(int /*aNpoints*/, UVector3 * /*aArray*/) const {}
|
||||
// o generates points on the edges of a solid - primarily for testing purposes
|
||||
// o for solids composed only of curved surfaces(like full spheres or toruses) or
|
||||
// where an implementation is not available, it defaults to PointOnSurface.
|
||||
|
||||
// Visualisation
|
||||
virtual void GetParametersList(int aNumber,double *aArray) const =0;
|
||||
|
||||
virtual VUSolid* Clone() const =0;
|
||||
// o provide a new object which is a clone of the solid
|
||||
|
||||
// Visualization
|
||||
|
||||
static double Tolerance() {return fgTolerance;}
|
||||
|
||||
inline virtual std::ostream& StreamInfo( std::ostream& os ) const = 0;
|
||||
|
||||
virtual UVector3 GetPointOnSurface() const = 0;
|
||||
|
||||
double EstimateCubicVolume(int nStat, double epsilon) const;
|
||||
// Calculate cubic volume based on Inside() method.
|
||||
// Accuracy is limited by the second argument or the statistics
|
||||
// expressed by the first argument.
|
||||
|
||||
double EstimateSurfaceArea(int nStat, double ell) const;
|
||||
// Calculate surface area only based on Inside() method.
|
||||
// Accuracy is limited by the second argument or the statistics
|
||||
// expressed by the first argument.
|
||||
|
||||
protected:
|
||||
virtual void ComputeBBox(UBBox *aBox, bool aStore = false) = 0;
|
||||
// o Compute the bounding box for the solid. Called automatically and stored ?
|
||||
// o Can throw an exception if the solid is invalid
|
||||
private:
|
||||
std::string fName; // Name of the solid
|
||||
//UBBox *fBBox; // Bounding box
|
||||
};
|
||||
inline double VUSolid::GetCarTolerance() const { return fgTolerance;}
|
||||
inline double VUSolid::GetRadTolerance() const { return frTolerance;}
|
||||
inline double VUSolid::GetAngTolerance() const { return faTolerance;}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
#------------------------------------------------------------------------------
|
||||
# sources.cmake
|
||||
# Module : G4geomUSolids
|
||||
# Package: Geant4.src.G4geometry.G4geomUSolids
|
||||
#
|
||||
# Sources description for a library.
|
||||
# Lists the sources and headers of the code explicitely.
|
||||
# Lists include paths needed.
|
||||
# Lists the internal granular and global dependencies of the library.
|
||||
# Source specific properties should be added at the end.
|
||||
#
|
||||
# Generated on : 24/9/2010
|
||||
#
|
||||
# $Id: sources.cmake 66356 2012-12-18 09:02:32Z gcosmo $
|
||||
#
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
# List external includes needed.
|
||||
include_directories(${CLHEP_INCLUDE_DIRS})
|
||||
|
||||
# List internal includes needed.
|
||||
include_directories(${CMAKE_SOURCE_DIR}/source/geometry/management/include)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/source/geometry/volumes/include)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/source/global/HEPGeometry/include)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/source/global/management/include)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/source/graphics_reps/include)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/source/intercoms/include)
|
||||
|
||||
#
|
||||
# Define the Geant4 Module.
|
||||
#
|
||||
include(Geant4MacroDefineModule)
|
||||
GEANT4_DEFINE_MODULE(NAME G4geomUSolids
|
||||
HEADERS
|
||||
G4USolid.hh
|
||||
UBits.hh
|
||||
UBox.hh
|
||||
UCons.hh
|
||||
UCons.icc
|
||||
UEnclosingCylinder.hh
|
||||
UGenericPolycone.hh
|
||||
UGenericPolycone.icc
|
||||
UIntersectingCone.hh
|
||||
UOrb.hh
|
||||
UPolycone.hh
|
||||
UPolycone.icc
|
||||
UPolyconeSide.hh
|
||||
UPolyhedra.hh
|
||||
UPolyhedra.icc
|
||||
UPolyhedraSide.hh
|
||||
UPolyPhiFace.hh
|
||||
UPolyPhiFace.icc
|
||||
UReduciblePolygon.hh
|
||||
USphere.hh
|
||||
UTet.hh
|
||||
UTransform3D.hh
|
||||
UTrd.hh
|
||||
UTrd.icc
|
||||
UTubs.hh
|
||||
UTubs.icc
|
||||
UTypes.hh
|
||||
UUtils.hh
|
||||
UVCSGface.hh
|
||||
UVCSGfaceted.hh
|
||||
UVector2.hh
|
||||
UVector2.icc
|
||||
UVector3.hh
|
||||
UVoxelizer.hh
|
||||
VUFacet.hh
|
||||
VUSolid.hh
|
||||
SOURCES
|
||||
G4USolid.cc
|
||||
UBits.cc
|
||||
UBox.cc
|
||||
UCons.cc
|
||||
UEnclosingCylinder.cc
|
||||
UGenericPolycone.cc
|
||||
UIntersectingCone.cc
|
||||
UOrb.cc
|
||||
UPolycone.cc
|
||||
UPolyconeSide.cc
|
||||
UPolyhedra.cc
|
||||
UPolyhedraSide.cc
|
||||
UPolyPhiFace.cc
|
||||
UReduciblePolygon.cc
|
||||
USphere.cc
|
||||
UTet.cc
|
||||
UTransform3D.cc
|
||||
UTrd.cc
|
||||
UTubs.cc
|
||||
UUtils.cc
|
||||
UVCSGfaceted.cc
|
||||
UVector2.cc
|
||||
UVector3.cc
|
||||
UVoxelizer.cc
|
||||
VUFacet.cc
|
||||
VUSolid.cc
|
||||
GRANULAR_DEPENDENCIES
|
||||
G4geometrymng
|
||||
G4globman
|
||||
G4graphics_reps
|
||||
G4intercoms
|
||||
G4volumes
|
||||
GLOBAL_DEPENDENCIES
|
||||
G4global
|
||||
G4graphics_reps
|
||||
G4intercoms
|
||||
LINK_LIBRARIES
|
||||
)
|
||||
|
||||
# List any source specific properties here
|
||||
|
||||
@@ -0,0 +1,557 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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:$
|
||||
// GEANT4 tag $Name:$
|
||||
//
|
||||
//
|
||||
// G4USolid implementation
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#include "G4USolid.hh"
|
||||
#include "G4AffineTransform.hh"
|
||||
#include "G4VoxelLimits.hh"
|
||||
#include "G4VGraphicsScene.hh"
|
||||
#include "G4Polyhedron.hh"
|
||||
#include "G4PolyhedronArbitrary.hh"
|
||||
#include "G4VisExtent.hh"
|
||||
#include "G4PhysicalConstants.hh"
|
||||
|
||||
G4USolid::G4USolid(const G4String& name, VUSolid* s) :
|
||||
G4VSolid(name), fShape(s), fPolyhedron(0)
|
||||
{
|
||||
}
|
||||
|
||||
G4USolid::G4USolid(__void__& a)
|
||||
: G4VSolid(a), fShape(0), fPolyhedron(0)
|
||||
{
|
||||
}
|
||||
|
||||
G4USolid::~G4USolid()
|
||||
{
|
||||
}
|
||||
|
||||
G4bool G4USolid::operator==(const G4USolid& s) const
|
||||
{
|
||||
return (this == &s) ? true : false;
|
||||
}
|
||||
|
||||
EInside G4USolid::Inside(const G4ThreeVector& p) const
|
||||
{
|
||||
UVector3 pt;
|
||||
VUSolid::EnumInside in_temp;
|
||||
EInside in = kOutside;
|
||||
pt.x = p.x();
|
||||
pt.y = p.y();
|
||||
pt.z = p.z(); // better assign at construction
|
||||
|
||||
in_temp = fShape->Inside(pt);
|
||||
|
||||
if (in_temp == VUSolid::eSurface)return kSurface;
|
||||
if (in_temp == VUSolid::eInside)return kInside;
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
G4ThreeVector G4USolid::SurfaceNormal(const G4ThreeVector& pt) const
|
||||
{
|
||||
UVector3 p;
|
||||
p.x = pt.x();
|
||||
p.y = pt.y();
|
||||
p.z = pt.z();
|
||||
UVector3 n;
|
||||
fShape->Normal(p, n);
|
||||
return G4ThreeVector(n.x, n.y, n.z);
|
||||
}
|
||||
|
||||
G4double G4USolid::DistanceToIn(const G4ThreeVector& pt,
|
||||
const G4ThreeVector& d)const
|
||||
{
|
||||
UVector3 p;
|
||||
p.x = pt.x();
|
||||
p.y = pt.y();
|
||||
p.z = pt.z(); // better assign at construction
|
||||
UVector3 v;
|
||||
v.x = d.x();
|
||||
v.y = d.y();
|
||||
v.z = d.z(); // better assign at construction
|
||||
G4double dist = fShape->DistanceToIn(p, v);
|
||||
if (dist > kInfinity) dist = kInfinity;
|
||||
return dist;
|
||||
}
|
||||
|
||||
G4double G4USolid::DistanceToIn(const G4ThreeVector& pt) const
|
||||
{
|
||||
UVector3 p;
|
||||
p.x = pt.x();
|
||||
p.y = pt.y();
|
||||
p.z = pt.z(); // better assign at construction
|
||||
G4double dist = fShape->SafetyFromOutside(p); // true?
|
||||
if (dist > kInfinity) dist = kInfinity;
|
||||
return dist;
|
||||
}
|
||||
|
||||
G4double G4USolid::DistanceToOut(const G4ThreeVector& pt,
|
||||
const G4ThreeVector& d,
|
||||
const G4bool calcNorm,
|
||||
G4bool* validNorm,
|
||||
G4ThreeVector* norm) const
|
||||
{
|
||||
UVector3 p;
|
||||
p.x = pt.x();
|
||||
p.y = pt.y();
|
||||
p.z = pt.z(); // better assign at construction
|
||||
UVector3 v;
|
||||
v.x = d.x();
|
||||
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
|
||||
if(calcNorm)
|
||||
{
|
||||
if(valid){ *validNorm = true;}
|
||||
else {* validNorm =false;}
|
||||
if(*validNorm)
|
||||
{ norm->setX(n.x);
|
||||
norm->setY(n.y);
|
||||
norm->setZ(n.z);
|
||||
} // *norm = n, but only after calcNorm check
|
||||
}
|
||||
if (dist > kInfinity) dist = kInfinity;
|
||||
return dist;
|
||||
}
|
||||
|
||||
G4double G4USolid::DistanceToOut(const G4ThreeVector& pt) const
|
||||
{
|
||||
UVector3 p;
|
||||
p.x = pt.x();
|
||||
p.y = pt.y();
|
||||
p.z = pt.z(); // better assign at construction
|
||||
return fShape->SafetyFromInside(p); // true?
|
||||
}
|
||||
|
||||
G4double G4USolid::GetCubicVolume()
|
||||
{
|
||||
return fShape->Capacity();
|
||||
}
|
||||
|
||||
G4double G4USolid::GetSurfaceArea()
|
||||
{
|
||||
return fShape->SurfaceArea();
|
||||
}
|
||||
|
||||
G4ThreeVector G4USolid::GetPointOnSurface() const
|
||||
{
|
||||
UVector3 p;
|
||||
p = fShape->GetPointOnSurface();
|
||||
return G4ThreeVector(p.x, p.y, p.z);
|
||||
}
|
||||
|
||||
G4bool G4USolid::CalculateExtent(const EAxis pAxis,
|
||||
const G4VoxelLimits& pVoxelLimit,
|
||||
const G4AffineTransform& pTransform,
|
||||
G4double& pMin, G4double& pMax) const
|
||||
{
|
||||
if (!pTransform.IsRotated())
|
||||
{
|
||||
VUSolid::EAxisType eAxis = VUSolid::eXaxis;
|
||||
G4double offset = pTransform.NetTranslation().x();
|
||||
if (pAxis == kYAxis)
|
||||
{
|
||||
eAxis = VUSolid::eYaxis;
|
||||
offset = pTransform.NetTranslation().y();
|
||||
}
|
||||
if (pAxis == kZAxis)
|
||||
{
|
||||
eAxis = VUSolid::eZaxis;
|
||||
offset = pTransform.NetTranslation().z();
|
||||
}
|
||||
fShape->ExtentAxis(eAxis, pMin, pMax);
|
||||
|
||||
pMin += offset;
|
||||
pMax += offset;
|
||||
|
||||
if (pVoxelLimit.IsLimited())
|
||||
{
|
||||
switch (pAxis)
|
||||
{
|
||||
case kXAxis:
|
||||
if ((pMin > pVoxelLimit.GetMaxXExtent() + kCarTolerance) ||
|
||||
(pMax < pVoxelLimit.GetMinXExtent() - kCarTolerance))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
pMin = std::max(pMin, pVoxelLimit.GetMinXExtent());
|
||||
pMax = std::min(pMax, pVoxelLimit.GetMaxXExtent());
|
||||
}
|
||||
break;
|
||||
case kYAxis:
|
||||
if ((pMin > pVoxelLimit.GetMaxYExtent() + kCarTolerance) ||
|
||||
(pMax < pVoxelLimit.GetMinYExtent() - kCarTolerance))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
pMin = std::max(pMin, pVoxelLimit.GetMinYExtent());
|
||||
pMax = std::min(pMax, pVoxelLimit.GetMaxYExtent());
|
||||
}
|
||||
break;
|
||||
case kZAxis:
|
||||
if ((pMin > pVoxelLimit.GetMaxZExtent() + kCarTolerance) ||
|
||||
(pMax < pVoxelLimit.GetMinZExtent() - kCarTolerance))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
pMin = std::max(pMin, pVoxelLimit.GetMinZExtent());
|
||||
pMax = std::min(pMax, pVoxelLimit.GetMaxZExtent());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
pMin -= kCarTolerance ;
|
||||
pMax += kCarTolerance ;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else // General rotated case - create and clip mesh to boundaries
|
||||
{
|
||||
// Rotate BoundingBox and Calculate Extent as for BREPS
|
||||
|
||||
G4bool existsAfterClip = false ;
|
||||
G4ThreeVectorList* vertices ;
|
||||
|
||||
pMin = +kInfinity ;
|
||||
pMax = -kInfinity ;
|
||||
|
||||
// Calculate rotated vertex coordinates
|
||||
|
||||
vertices = CreateRotatedVertices(pTransform) ;
|
||||
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(pTransform.Inverse().TransformPoint(clipCentre)) != kOutside)
|
||||
{
|
||||
pMin = pVoxelLimit.GetMinExtent(pAxis);
|
||||
}
|
||||
else
|
||||
{
|
||||
pMin -= kCarTolerance;
|
||||
}
|
||||
clipCentre(pAxis) = pVoxelLimit.GetMaxExtent(pAxis);
|
||||
|
||||
if (Inside(pTransform.Inverse().TransformPoint(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(pTransform.Inverse().TransformPoint(clipCentre))
|
||||
!= kOutside)
|
||||
{
|
||||
existsAfterClip = true ;
|
||||
pMin = pVoxelLimit.GetMinExtent(pAxis) ;
|
||||
pMax = pVoxelLimit.GetMaxExtent(pAxis) ;
|
||||
}
|
||||
}
|
||||
delete vertices;
|
||||
return existsAfterClip;
|
||||
}
|
||||
}
|
||||
|
||||
void G4USolid::DescribeYourselfTo(G4VGraphicsScene& scene) const
|
||||
{
|
||||
scene.AddSolid(*this);
|
||||
}
|
||||
G4GeometryType G4USolid::GetEntityType() const
|
||||
{
|
||||
|
||||
G4String string = fShape->GetEntityType();
|
||||
return "G4" + string;
|
||||
}
|
||||
|
||||
std::ostream& G4USolid::StreamInfo(std::ostream& os) const
|
||||
{
|
||||
os << "-----------------------------------------------------------\n"
|
||||
<< " *** Dump for solid - " << fShape->GetName() << " ***\n";
|
||||
// << " ===================================================\n"
|
||||
// << " Solid type: " << fShape->GetEntityType() << "\n"
|
||||
// << "-----------------------------------------------------------\n";
|
||||
|
||||
return os;//fShape->StreamInfo(os);
|
||||
}
|
||||
|
||||
G4USolid::G4USolid(const G4USolid& rhs)
|
||||
: G4VSolid(rhs), fShape(rhs.fShape), fPolyhedron(rhs.fPolyhedron)
|
||||
{
|
||||
}
|
||||
|
||||
G4USolid& G4USolid::operator=(const G4USolid& rhs)
|
||||
{
|
||||
// Check assignment to self
|
||||
//
|
||||
if (this == &rhs)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Copy base class data
|
||||
//
|
||||
G4VSolid::operator=(rhs);
|
||||
|
||||
// Copy data
|
||||
//
|
||||
fShape = rhs.fShape;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
G4VSolid* G4USolid::Clone() const
|
||||
{
|
||||
return new G4USolid(fShape->GetName(), fShape->Clone());
|
||||
}
|
||||
|
||||
G4ThreeVectorList*
|
||||
G4USolid::CreateRotatedVertices(const G4AffineTransform& pTransform) const
|
||||
{
|
||||
G4double xMin, xMax, yMin, yMax, zMin, zMax;
|
||||
|
||||
fShape->ExtentAxis(VUSolid::eXaxis, xMin, xMax);
|
||||
fShape->ExtentAxis(VUSolid::eYaxis, yMin, yMax);
|
||||
fShape->ExtentAxis(VUSolid::eZaxis, zMin, zMax);
|
||||
|
||||
G4ThreeVectorList* vertices;
|
||||
vertices = new G4ThreeVectorList();
|
||||
|
||||
if (vertices)
|
||||
{
|
||||
vertices->reserve(8);
|
||||
G4ThreeVector vertex0(xMin, yMin, zMin);
|
||||
G4ThreeVector vertex1(xMax, yMin, zMin);
|
||||
G4ThreeVector vertex2(xMax, yMax, zMin);
|
||||
G4ThreeVector vertex3(xMin, yMax, zMin);
|
||||
G4ThreeVector vertex4(xMin, yMin, zMax);
|
||||
G4ThreeVector vertex5(xMax, yMin, zMax);
|
||||
G4ThreeVector vertex6(xMax, yMax, zMax);
|
||||
G4ThreeVector vertex7(xMin, yMax, zMax);
|
||||
|
||||
vertices->push_back(pTransform.TransformPoint(vertex0));
|
||||
vertices->push_back(pTransform.TransformPoint(vertex1));
|
||||
vertices->push_back(pTransform.TransformPoint(vertex2));
|
||||
vertices->push_back(pTransform.TransformPoint(vertex3));
|
||||
vertices->push_back(pTransform.TransformPoint(vertex4));
|
||||
vertices->push_back(pTransform.TransformPoint(vertex5));
|
||||
vertices->push_back(pTransform.TransformPoint(vertex6));
|
||||
vertices->push_back(pTransform.TransformPoint(vertex7));
|
||||
}
|
||||
else
|
||||
{
|
||||
G4Exception("G4VUSolid::CreateRotatedVertices()", "FatalError",
|
||||
FatalException, "Out of memory - Cannot allocate vertices!");
|
||||
}
|
||||
return vertices;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
G4Polyhedron* G4USolid::GetPolyhedron() const
|
||||
{
|
||||
if (!fPolyhedron) fPolyhedron = CreatePolyhedron();
|
||||
return fPolyhedron;
|
||||
}
|
||||
|
||||
void G4USolid::ResetPolyhedron() const
|
||||
{
|
||||
if (fPolyhedron) delete fPolyhedron;
|
||||
fPolyhedron = 0;
|
||||
}
|
||||
G4VisExtent G4USolid:: GetExtent() const
|
||||
{
|
||||
G4VisExtent extent;
|
||||
G4VoxelLimits voxelLimits; // Defaults to "infinite" limits.
|
||||
G4AffineTransform affineTransform;
|
||||
G4double vmin, vmax;
|
||||
CalculateExtent(kXAxis, voxelLimits, affineTransform, vmin, vmax);
|
||||
extent.SetXmin(vmin);
|
||||
extent.SetXmax(vmax);
|
||||
CalculateExtent(kYAxis, voxelLimits, affineTransform, vmin, vmax);
|
||||
extent.SetYmin(vmin);
|
||||
extent.SetYmax(vmax);
|
||||
CalculateExtent(kZAxis, voxelLimits, affineTransform, vmin, vmax);
|
||||
extent.SetZmin(vmin);
|
||||
extent.SetZmax(vmax);
|
||||
return extent;
|
||||
}
|
||||
@@ -0,0 +1,458 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UBits
|
||||
//
|
||||
// 19.10.12 Marek Gayer
|
||||
// Created from original implementation in ROOT (TBits)
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#include "UBits.hh"
|
||||
#include <stdio.h>
|
||||
//______________________________________________________________________________
|
||||
UBits::UBits(unsigned int nBits) : fNBits(nBits)
|
||||
{
|
||||
// UBits constructor. All bits set to 0
|
||||
|
||||
if (fNBits <= 0) fNBits = 0;
|
||||
fNBytes = fNBits ? ((fNBits - 1) / 8) + 1 : 1;
|
||||
fAllBits = new unsigned char[fNBytes];
|
||||
// this is redundant only with libNew
|
||||
std::memset(fAllBits, 0, fNBytes);
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
UBits::UBits(const UBits& original) : fNBits(original.fNBits),
|
||||
fNBytes(original.fNBytes)
|
||||
{
|
||||
// UBits copy constructor
|
||||
|
||||
fAllBits = new unsigned char[fNBytes];
|
||||
std::memcpy(fAllBits, original.fAllBits, fNBytes);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//______________________________________________________________________________
|
||||
UBits& UBits::operator=(const UBits& rhs)
|
||||
{
|
||||
// UBits assignment operator
|
||||
// Check assignment to self
|
||||
if (this == &rhs) { return *this; }
|
||||
|
||||
// TObject::operator=(rhs);
|
||||
fNBits = rhs.fNBits;
|
||||
fNBytes = rhs.fNBytes;
|
||||
delete [] fAllBits;
|
||||
if (fNBytes != 0) {
|
||||
fAllBits = new unsigned char[fNBytes];
|
||||
std::memcpy(fAllBits,rhs.fAllBits,fNBytes);
|
||||
} else {
|
||||
fAllBits = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
UBits::~UBits()
|
||||
{
|
||||
// UBits destructor
|
||||
|
||||
delete [] fAllBits;
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
void UBits::Clear()
|
||||
{
|
||||
// Clear the value.
|
||||
|
||||
delete [] fAllBits;
|
||||
fAllBits = 0;
|
||||
fNBits = 0;
|
||||
fNBytes = 0;
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
void UBits::Compact()
|
||||
{
|
||||
// Reduce the storage used by the object to a minimun
|
||||
|
||||
if (!fNBits || !fAllBits) return;
|
||||
unsigned int needed;
|
||||
for (needed = fNBytes - 1;
|
||||
needed > 0 && fAllBits[needed] == 0;)
|
||||
{
|
||||
needed--;
|
||||
};
|
||||
needed++;
|
||||
|
||||
if (needed != fNBytes)
|
||||
{
|
||||
unsigned char* old_location = fAllBits;
|
||||
fAllBits = new unsigned char[needed];
|
||||
|
||||
std::memcpy(fAllBits, old_location, needed);
|
||||
delete [] old_location;
|
||||
|
||||
fNBytes = needed;
|
||||
fNBits = 8 * fNBytes;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
//______________________________________________________________________________
|
||||
unsigned int UBits::CounUBits(unsigned int startBit) const
|
||||
{
|
||||
// Return number of bits set to 1 starting at bit startBit
|
||||
|
||||
static const int nBitsCached[256] = {
|
||||
0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,
|
||||
1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
|
||||
1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
|
||||
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
|
||||
1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
|
||||
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
|
||||
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
|
||||
3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
|
||||
1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
|
||||
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
|
||||
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
|
||||
3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
|
||||
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
|
||||
3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
|
||||
3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
|
||||
4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8};
|
||||
|
||||
unsigned int i,count = 0;
|
||||
if (startBit == 0) {
|
||||
for(i=0; i<fNBytes; i++) {
|
||||
count += nBitsCached[fAllBits[i]];
|
||||
}
|
||||
return count;
|
||||
}
|
||||
if (startBit >= fNBits) return count;
|
||||
unsigned int startByte = startBit/8;
|
||||
unsigned int ibit = startBit%8;
|
||||
if (ibit) {
|
||||
for (i=ibit;i<8;i++) {
|
||||
if (fAllBits[startByte] & (1<<ibit)) count++;
|
||||
}
|
||||
startByte++;
|
||||
}
|
||||
for(i=startByte; i<fNBytes; i++) {
|
||||
count += nBitsCached[fAllBits[i]];
|
||||
}
|
||||
return count;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
//______________________________________________________________________________
|
||||
void UBits::DoAndEqual(const UBits& rhs)
|
||||
{
|
||||
// Execute (*this) &= rhs;
|
||||
// Extra bits in rhs are ignored
|
||||
// Missing bits in rhs are assumed to be zero.
|
||||
|
||||
unsigned int min = (fNBytes<rhs.fNBytes) ? fNBytes : rhs.fNBytes;
|
||||
for(unsigned int i=0; i<min; ++i) {
|
||||
fAllBits[i] &= rhs.fAllBits[i];
|
||||
}
|
||||
if (fNBytes>min) {
|
||||
std::memset(&(fAllBits[min]),0,fNBytes-min);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
//______________________________________________________________________________
|
||||
void UBits::DoOrEqual(const UBits& rhs)
|
||||
{
|
||||
// Execute (*this) &= rhs;
|
||||
// Extra bits in rhs are ignored
|
||||
// Missing bits in rhs are assumed to be zero.
|
||||
|
||||
unsigned int min = (fNBytes<rhs.fNBytes) ? fNBytes : rhs.fNBytes;
|
||||
for(unsigned int i=0; i<min; ++i) {
|
||||
fAllBits[i] |= rhs.fAllBits[i];
|
||||
}
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
void UBits::DoXorEqual(const UBits& rhs)
|
||||
{
|
||||
// Execute (*this) ^= rhs;
|
||||
// Extra bits in rhs are ignored
|
||||
// Missing bits in rhs are assumed to be zero.
|
||||
|
||||
unsigned int min = (fNBytes<rhs.fNBytes) ? fNBytes : rhs.fNBytes;
|
||||
for(unsigned int i=0; i<min; ++i) {
|
||||
fAllBits[i] ^= rhs.fAllBits[i];
|
||||
}
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
void UBits::DoFlip()
|
||||
{
|
||||
// Execute ~(*this)
|
||||
|
||||
for(unsigned int i=0; i<fNBytes; ++i) {
|
||||
fAllBits[i] = ~fAllBits[i];
|
||||
}
|
||||
// NOTE: out-of-bounds bit were also flipped!
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
void UBits::DoLeftShift(unsigned int shift)
|
||||
{
|
||||
// Execute the left shift operation.
|
||||
|
||||
if (shift==0) return;
|
||||
const unsigned int wordshift = shift / 8;
|
||||
const unsigned int offset = shift % 8;
|
||||
if (offset==0) {
|
||||
for(unsigned int n = fNBytes - 1; n >= wordshift; --n) {
|
||||
fAllBits[n] = fAllBits[ n - wordshift ];
|
||||
}
|
||||
} else {
|
||||
const unsigned int sub_offset = 8 - offset;
|
||||
for(unsigned int n = fNBytes - 1; n > wordshift; --n) {
|
||||
fAllBits[n] = (fAllBits[n - wordshift] << offset) |
|
||||
(fAllBits[n - wordshift - 1] >> sub_offset);
|
||||
}
|
||||
fAllBits[wordshift] = fAllBits[0] << offset;
|
||||
}
|
||||
std::memset(fAllBits,0,wordshift);
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
void UBits::DoRightShift(unsigned int shift)
|
||||
{
|
||||
// Execute the left shift operation.
|
||||
|
||||
if (shift==0) return;
|
||||
const unsigned int wordshift = shift / 8;
|
||||
const unsigned int offset = shift % 8;
|
||||
const unsigned int limit = fNBytes - wordshift - 1;
|
||||
|
||||
if (offset == 0)
|
||||
for (unsigned int n = 0; n <= limit; ++n)
|
||||
fAllBits[n] = fAllBits[n + wordshift];
|
||||
else
|
||||
{
|
||||
const unsigned int sub_offset = 8 - offset;
|
||||
for (unsigned int n = 0; n < limit; ++n)
|
||||
fAllBits[n] = (fAllBits[n + wordshift] >> offset) |
|
||||
(fAllBits[n + wordshift + 1] << sub_offset);
|
||||
fAllBits[limit] = fAllBits[fNBytes-1] >> offset;
|
||||
}
|
||||
|
||||
std::memset(&(fAllBits[limit + 1]),0, fNBytes - limit - 1);
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
//______________________________________________________________________________
|
||||
unsigned int UBits::FirstNullBit(unsigned int startBit) const
|
||||
{
|
||||
// Return position of first null bit (starting from position 0 and up)
|
||||
|
||||
static const int fbits[256] = {
|
||||
0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
|
||||
0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
|
||||
0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
|
||||
0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,
|
||||
0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
|
||||
0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
|
||||
0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
|
||||
0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,
|
||||
0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
|
||||
0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
|
||||
0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
|
||||
0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,
|
||||
0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
|
||||
0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
|
||||
0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
|
||||
0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,8};
|
||||
|
||||
unsigned int i;
|
||||
if (startBit == 0) {
|
||||
for(i=0; i<fNBytes; i++) {
|
||||
if (fAllBits[i] != 255) return 8*i + fbits[fAllBits[i]];
|
||||
}
|
||||
return fNBits;
|
||||
}
|
||||
if (startBit >= fNBits) return fNBits;
|
||||
unsigned int startByte = startBit/8;
|
||||
unsigned int ibit = startBit%8;
|
||||
if (ibit) {
|
||||
for (i=ibit;i<8;i++) {
|
||||
if ((fAllBits[startByte] & (1<<i)) == 0) return 8*startByte+i;
|
||||
}
|
||||
startByte++;
|
||||
}
|
||||
for(i=startByte; i<fNBytes; i++) {
|
||||
if (fAllBits[i] != 255) return 8*i + fbits[fAllBits[i]];
|
||||
}
|
||||
return fNBits;
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
unsigned int UBits::FirstSetBit(unsigned int startBit) const
|
||||
{
|
||||
// Return position of first non null bit (starting from position 0 and up)
|
||||
|
||||
static const int fbits[256] = {
|
||||
8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
|
||||
4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
|
||||
5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
|
||||
4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
|
||||
6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
|
||||
4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
|
||||
5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
|
||||
4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
|
||||
7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
|
||||
4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
|
||||
5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
|
||||
4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
|
||||
6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
|
||||
4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
|
||||
5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
|
||||
4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0};
|
||||
|
||||
unsigned int i;
|
||||
if (startBit == 0) {
|
||||
for(i=0; i<fNBytes; i++) {
|
||||
if (fAllBits[i] != 0) return 8*i + fbits[fAllBits[i]];
|
||||
}
|
||||
return fNBits;
|
||||
}
|
||||
if (startBit >= fNBits) return fNBits;
|
||||
unsigned int startByte = startBit/8;
|
||||
unsigned int ibit = startBit%8;
|
||||
if (ibit) {
|
||||
for (i=ibit;i<8;i++) {
|
||||
if ((fAllBits[startByte] & (1<<i)) != 0) return 8*startByte+i;
|
||||
}
|
||||
startByte++;
|
||||
}
|
||||
for(i=startByte; i<fNBytes; i++) {
|
||||
if (fAllBits[i] != 0) return 8*i + fbits[fAllBits[i]];
|
||||
}
|
||||
return fNBits;
|
||||
}
|
||||
*/
|
||||
|
||||
//______________________________________________________________________________
|
||||
void UBits::Output(std::ostream& os) const
|
||||
{
|
||||
// Print the value to the std::ostream
|
||||
for (unsigned int i = 0; i < fNBytes; ++i)
|
||||
{
|
||||
unsigned char val = fAllBits[fNBytes - 1 - i];
|
||||
for (unsigned int j = 0; j < 8; ++j)
|
||||
{
|
||||
os << (bool)(val & 0x80);
|
||||
val <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
void UBits::Print() const
|
||||
{
|
||||
// Print the list of active bits
|
||||
int count = 0;
|
||||
for (unsigned int i = 0; i < fNBytes; ++i)
|
||||
{
|
||||
unsigned char val = fAllBits[i];
|
||||
for (unsigned int j = 0; j < 8; ++j)
|
||||
{
|
||||
if (val & 1) printf(" bit:%4d = 1\n", count);
|
||||
count++;
|
||||
val = val >> 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
void UBits::ResetAllBits(bool value)
|
||||
{
|
||||
if (fAllBits) std::memset(fAllBits, value ? 0xFF : 0, fNBytes);
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
void UBits::ReserveBytes(unsigned int nbytes)
|
||||
{
|
||||
// Reverse each bytes.
|
||||
|
||||
if (nbytes > fNBytes)
|
||||
{
|
||||
// do it in this order to remain exception-safe.
|
||||
unsigned char* newBits = new unsigned char[nbytes];
|
||||
delete[] fAllBits;
|
||||
fNBytes = nbytes;
|
||||
fAllBits = newBits;
|
||||
}
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
void UBits::Set(unsigned int nBits, const char* array)
|
||||
{
|
||||
// Set all the bytes
|
||||
unsigned int nbytes = (nBits + 7) >> 3;
|
||||
|
||||
ReserveBytes(nbytes);
|
||||
|
||||
fNBits = nBits;
|
||||
std::memcpy(fAllBits, array, nbytes);
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
void UBits::Get(char* array) const
|
||||
{
|
||||
// Copy all the byes.
|
||||
std::memcpy(array, fAllBits, (fNBits + 7) >> 3);
|
||||
}
|
||||
|
||||
// If we are on a little endian machine, a bitvector represented using
|
||||
// any integer type is identical to a bitvector represented using bytes. -- FP.
|
||||
|
||||
|
||||
void UBits::Set(unsigned int nBits, const int* array)
|
||||
{
|
||||
// Set all the bytes.
|
||||
|
||||
Set(nBits, (const char*)array);
|
||||
}
|
||||
|
||||
void UBits::Get(int* array) const
|
||||
{
|
||||
// Get all the bytes.
|
||||
|
||||
Get((char*)array);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
bool UBits::operator==(const UBits &other) const
|
||||
{
|
||||
// Compare object.
|
||||
|
||||
if (fNBits == other.fNBits) {
|
||||
return !memcmp(fAllBits, other.fAllBits, (fNBits+7)>>3);
|
||||
} else if (fNBits < other.fNBits) {
|
||||
return !memcmp(fAllBits, other.fAllBits, (fNBits+7)>>3) && other.FirstSetBit(fNBits) == other.fNBits;
|
||||
} else {
|
||||
return !memcmp(fAllBits, other.fAllBits, (other.fNBits+7)>>3) && FirstSetBit(other.fNBits) == fNBits;
|
||||
}
|
||||
}
|
||||
*/
|
||||
@@ -0,0 +1,551 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UBox
|
||||
//
|
||||
// 10.06.11 J.Apostolakis, G.Cosmo, A.Gheata
|
||||
// Created from original implementation in Geant4 and ROOT
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include "UUtils.hh"
|
||||
#include "UBox.hh"
|
||||
|
||||
//______________________________________________________________________________
|
||||
UBox::UBox(const std::string& name, double dx, double dy, double dz)
|
||||
: VUSolid(name),
|
||||
fDx(dx),
|
||||
fDy(dy),
|
||||
fDz(dz), fCubicVolume(0.), fSurfaceArea(0.)
|
||||
{
|
||||
// Named constructor
|
||||
|
||||
if ((dx < 2 * VUSolid::fgTolerance)
|
||||
|| (dy < 2 * VUSolid::fgTolerance)
|
||||
|| (dz < 2 * VUSolid::fgTolerance)) // limit to thickness of surfaces
|
||||
{
|
||||
//std::ostringstream message;
|
||||
std::ostringstream message;
|
||||
message << "Dimensions too small for Solid: " << GetName() << "!" << std::endl
|
||||
<< " dx, dy, dz = " << dx << ", " << dy << ", " << dz;
|
||||
UUtils::Exception("UBox::UBox()", "UGeomSolids", FatalErrorInArguments, 1, message.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void UBox::Set(double dx, double dy, double dz)
|
||||
{
|
||||
fDx = dx;
|
||||
fDy = dy;
|
||||
fDz = dz;
|
||||
}
|
||||
|
||||
void UBox::Set(const UVector3& vec)
|
||||
{
|
||||
fDx = vec.x;
|
||||
fDy = vec.y;
|
||||
fDz = vec.z;
|
||||
}
|
||||
//Destructor
|
||||
UBox::~UBox()
|
||||
{
|
||||
|
||||
}
|
||||
// Copy constructor
|
||||
|
||||
UBox::UBox(const UBox& rhs)
|
||||
: VUSolid(rhs), fDx(rhs.fDx), fDy(rhs.fDy), fDz(rhs.fDz),
|
||||
fCubicVolume(rhs.fCubicVolume), fSurfaceArea(rhs.fSurfaceArea)
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Assignment operator
|
||||
|
||||
UBox& UBox::operator = (const UBox& rhs)
|
||||
{
|
||||
// Check assignment to self
|
||||
//
|
||||
if (this == &rhs)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Copy base class data
|
||||
//
|
||||
VUSolid::operator=(rhs);
|
||||
|
||||
// Copy data
|
||||
//
|
||||
fDx = rhs.fDx;
|
||||
fDy = rhs.fDy;
|
||||
fDz = rhs.fDz;
|
||||
fCubicVolume = rhs.fCubicVolume;
|
||||
fSurfaceArea = rhs.fSurfaceArea;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
VUSolid::EnumInside UBox::Inside(const UVector3& aPoint) const
|
||||
{
|
||||
// Classify point location with respect to solid:
|
||||
// o eInside - inside the solid
|
||||
// o eSurface - close to surface within tolerance
|
||||
// o eOutside - outside the solid
|
||||
static const double delta = VUSolid::fgTolerance;
|
||||
// Early returns on outside condition on any axis. Check Z first for faster
|
||||
// exclusion in phi symmetric geometries.
|
||||
double ddz = std::abs(aPoint.z) - fDz;
|
||||
if (ddz > delta) return eOutside;
|
||||
double ddx = std::abs(aPoint.x) - fDx;
|
||||
if (ddx > delta) return eOutside;
|
||||
double ddy = std::abs(aPoint.y) - fDy;
|
||||
if (ddy > delta) return eOutside;
|
||||
if (ddx > - delta || ddy > -delta || ddz > -delta) return eSurface;
|
||||
return eInside;
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
double UBox::DistanceToIn(const UVector3& aPoint,
|
||||
const UVector3& aDirection,
|
||||
// UVector3 &aNormal,
|
||||
double aPstep) const
|
||||
{
|
||||
// Computes distance from a point presumably outside the solid to the solid
|
||||
// surface. Ignores first surface if the point is actually inside. Early return
|
||||
// infinity in case the safety to any surface is found greater than the proposed
|
||||
// step aPstep.
|
||||
// The normal vector to the crossed surface is filled only in case the box is
|
||||
// crossed, otherwise aNormal.IsNull() is true.
|
||||
|
||||
// Compute safety to the closest surface on each axis.
|
||||
// Early exits if safety bigger than proposed step.
|
||||
static const double delta = VUSolid::fgTolerance;
|
||||
// aNormal.SetNull();
|
||||
double safx = std::abs(aPoint.x) - fDx;
|
||||
double safy = std::abs(aPoint.y) - fDy;
|
||||
double safz = std::abs(aPoint.z) - fDz;
|
||||
if ((safx > aPstep) || (safy > aPstep) || (safz > aPstep))
|
||||
return UUtils::kInfinity;
|
||||
// Check numerical outside.
|
||||
bool outside = (safx > 0) || (safy > 0) || (safz > 0);
|
||||
if (!outside)
|
||||
{
|
||||
// If point close to this surface, check against the normal
|
||||
if (safx > -delta)
|
||||
{
|
||||
// aNormal.x = UUtils::Sign(1.0, aPoint.x);
|
||||
return (aPoint.x * aDirection.x > 0) ? UUtils::kInfinity : 0.0;
|
||||
}
|
||||
if (safy > -delta)
|
||||
{
|
||||
// aNormal.y = UUtils::Sign(1.0, aPoint.y);
|
||||
return (aPoint.y * aDirection.y > 0) ? UUtils::kInfinity : 0.0;
|
||||
}
|
||||
if (safz > -delta)
|
||||
{
|
||||
// aNormal.z = UUtils::Sign(1.0, aPoint.z);
|
||||
return (aPoint.z * aDirection.z > 0) ? UUtils::kInfinity : 0.0;
|
||||
}
|
||||
// Point actually "deep" inside, return zero distance, normal un-defined
|
||||
return 0.0;
|
||||
}
|
||||
// The point is really outside. Only axis with positive safety to be
|
||||
// considered. Early exit on each axis if point and direction components
|
||||
// have the same .sign.
|
||||
double dist = 0.0;
|
||||
double coordinate = 0.0;
|
||||
if (safx > 0)
|
||||
{
|
||||
if (aPoint.x * aDirection.x >= 0) return UUtils::kInfinity;
|
||||
dist = safx / std::abs(aDirection.x);
|
||||
coordinate = aPoint.y + dist * aDirection.y;
|
||||
if (std::abs(coordinate) < fDy)
|
||||
{
|
||||
coordinate = aPoint.z + dist * aDirection.z;
|
||||
if (std::abs(coordinate) < fDz)
|
||||
{
|
||||
// aNormal.x = UUtils::Sign(1.0, aPoint.x);
|
||||
if (dist < 0.5 * delta) dist = 0.;
|
||||
return dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (safy > 0)
|
||||
{
|
||||
if (aPoint.y * aDirection.y >= 0) return UUtils::kInfinity;
|
||||
dist = safy / std::abs(aDirection.y);
|
||||
coordinate = aPoint.x + dist * aDirection.x;
|
||||
if (std::abs(coordinate) < fDx)
|
||||
{
|
||||
coordinate = aPoint.z + dist * aDirection.z;
|
||||
if (std::abs(coordinate) < fDz)
|
||||
{
|
||||
// aNormal.y = UUtils::Sign(1.0, aPoint.y);
|
||||
if (dist < 0.5 * delta) dist = 0.;
|
||||
return dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (safz > 0)
|
||||
{
|
||||
if (aPoint.z * aDirection.z >= 0) return UUtils::kInfinity;
|
||||
dist = safz / std::abs(aDirection.z);
|
||||
coordinate = aPoint.x + dist * aDirection.x;
|
||||
if (std::abs(coordinate) < fDx)
|
||||
{
|
||||
coordinate = aPoint.y + dist * aDirection.y;
|
||||
if (std::abs(coordinate) < fDy)
|
||||
{
|
||||
// aNormal.z = UUtils::Sign(1.0, aPoint.z);
|
||||
if (dist < 0.5 * delta) dist = 0.;
|
||||
return dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
return UUtils::kInfinity;
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
double UBox::DistanceToOut(const UVector3& aPoint, const UVector3& aDirection,
|
||||
UVector3& aNormal,
|
||||
bool& convex,
|
||||
double /*aPstep*/) const
|
||||
{
|
||||
// Computes distance from a point presumably intside the solid to the solid
|
||||
// surface. Ignores first surface along each axis systematically (for points
|
||||
// inside or outside. Early returns zero in case the second surface is behind
|
||||
// the starting point.
|
||||
// o The proposed step is ignored.
|
||||
// o The normal vector to the crossed surface is always filled.
|
||||
double smin = UUtils::kInfinity;
|
||||
double snxt, signDir;
|
||||
convex = true; // Box is convex (even if the starting point is outside)
|
||||
// Check always the "away" surface along direction on axis. This responds
|
||||
// corectly even for points outside the solid (no need for tolerance check)
|
||||
if (aDirection.x != 0.0)
|
||||
{
|
||||
signDir = UUtils::Sign(1.0, aDirection.x);
|
||||
aNormal.Set(signDir, 0., 0.);
|
||||
snxt = (-aPoint.x + signDir * fDx) / aDirection.x;
|
||||
if (snxt <= 0) return 0.0; // point outside moving outwards
|
||||
smin = snxt;
|
||||
}
|
||||
|
||||
if (aDirection.y != 0.0)
|
||||
{
|
||||
signDir = UUtils::Sign(1.0, aDirection.y);
|
||||
snxt = (-aPoint.y + signDir * fDy) / aDirection.y;
|
||||
if (snxt <= 0)
|
||||
{
|
||||
aNormal.Set(0., signDir, 0.);
|
||||
return 0.0; // point outside moving outwards
|
||||
}
|
||||
if (snxt < smin)
|
||||
{
|
||||
smin = snxt;
|
||||
aNormal.Set(0., signDir, 0.);
|
||||
}
|
||||
}
|
||||
|
||||
if (aDirection.z != 0.0)
|
||||
{
|
||||
signDir = UUtils::Sign(1.0, aDirection.z);
|
||||
snxt = (-aPoint.z + signDir * fDz) / aDirection.z;
|
||||
if (snxt <= 0)
|
||||
{
|
||||
aNormal.Set(0., 0., signDir);
|
||||
return 0.0; // point outside moving outwards
|
||||
}
|
||||
if (snxt < smin)
|
||||
{
|
||||
smin = snxt;
|
||||
aNormal.Set(0., 0., signDir);
|
||||
}
|
||||
}
|
||||
if (smin < 0.5 * VUSolid::fgTolerance) smin = 0.;
|
||||
return smin;
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
double UBox::SafetyFromInside(const UVector3& aPoint,
|
||||
bool /*aAccurate*/) const
|
||||
{
|
||||
// Estimates the isotropic safety from a point inside the current solid to any
|
||||
// of its surfaces. The algorithm may be accurate or should provide a fast
|
||||
// underestimate.
|
||||
double safe, safy, safz;
|
||||
safe = fDx - std::abs(aPoint.x);
|
||||
safy = fDy - std::abs(aPoint.y);
|
||||
if (safy < safe) safe = safy;
|
||||
safz = fDz - std::abs(aPoint.z);
|
||||
if (safz < safe) safe = safz;
|
||||
return std::max(0.0, safe);
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
double UBox::SafetyFromOutside(const UVector3& aPoint,
|
||||
bool aAccurate) const
|
||||
{
|
||||
// Estimates the isotropic safety from a point outside the current solid to any
|
||||
// of its surfaces. The algorithm may be accurate or should provide a fast
|
||||
// underestimate.
|
||||
double safe, safx, safy, safz;
|
||||
safe = safx = -fDx + std::abs(aPoint.x);
|
||||
safy = -fDy + std::abs(aPoint.y);
|
||||
if (safy > safe) safe = safy;
|
||||
safz = -fDz + std::abs(aPoint.z);
|
||||
if (safz > safe) safe = safz;
|
||||
if (safe < 0.0) return 0.0; // point is inside
|
||||
if (!aAccurate) return safe;
|
||||
double safsq = 0.0;
|
||||
int count = 0;
|
||||
if (safx > 0)
|
||||
{
|
||||
safsq += safx * safx;
|
||||
count++;
|
||||
}
|
||||
if (safy > 0)
|
||||
{
|
||||
safsq += safy * safy;
|
||||
count++;
|
||||
}
|
||||
if (safz > 0)
|
||||
{
|
||||
safsq += safz * safz;
|
||||
count++;
|
||||
}
|
||||
if (count == 1) return safe;
|
||||
return std::sqrt(safsq);
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
bool UBox::Normal(const UVector3& aPoint, UVector3& aNormal) const
|
||||
{
|
||||
// Computes the normal on a surface and returns it as a unit vector
|
||||
// In case a point is further than tolerance_normal from a surface, set validNormal=false
|
||||
// Must return a valid vector. (even if the point is not on the surface.)
|
||||
//
|
||||
// On an edge or corner, provide an average normal of all facets within tolerance
|
||||
// NOTE: the tolerance value used in here is not yet the global surface
|
||||
// tolerance - we will have to revise this value - TODO
|
||||
static const double delta = 100.*VUSolid::fgTolerance;
|
||||
static const double kInvSqrt2 = 1. / std::sqrt(2.);
|
||||
static const double kInvSqrt3 = 1. / std::sqrt(3.);
|
||||
aNormal.Set(0.);
|
||||
UVector3 crt_normal, min_normal;
|
||||
int nsurf = 0;
|
||||
double safx = std::abs(std::abs(aPoint.x) - fDx);
|
||||
double safmin = safx;
|
||||
crt_normal.Set(UUtils::Sign(1., aPoint.x), 0., 0.);
|
||||
min_normal = crt_normal;
|
||||
if (safx < delta)
|
||||
{
|
||||
nsurf++;
|
||||
aNormal += crt_normal;
|
||||
}
|
||||
double safy = std::abs(std::abs(aPoint.y) - fDy);
|
||||
crt_normal.Set(0., UUtils::Sign(1., aPoint.y), 0.);
|
||||
if (safy < delta)
|
||||
{
|
||||
nsurf++;
|
||||
aNormal += crt_normal;
|
||||
}
|
||||
if (safy < safmin)
|
||||
{
|
||||
min_normal = crt_normal;
|
||||
safmin = safy;
|
||||
}
|
||||
double safz = std::abs(std::abs(aPoint.z) - fDz);
|
||||
crt_normal.Set(0., 0., UUtils::Sign(1., aPoint.z));
|
||||
if (safz < delta)
|
||||
{
|
||||
nsurf++;
|
||||
aNormal += crt_normal;
|
||||
}
|
||||
if (safz < safmin)
|
||||
{
|
||||
min_normal = crt_normal;
|
||||
safmin = safz;
|
||||
}
|
||||
|
||||
bool valid = true;
|
||||
switch (nsurf)
|
||||
{
|
||||
case 0:
|
||||
aNormal = min_normal;
|
||||
valid = false;
|
||||
break;
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
aNormal *= kInvSqrt2;
|
||||
break;
|
||||
case 3:
|
||||
aNormal *= kInvSqrt3;
|
||||
};
|
||||
return valid;
|
||||
}
|
||||
|
||||
|
||||
//______________________________________________________________________________
|
||||
void UBox::Extent(UVector3& aMin, UVector3& aMax) const
|
||||
{
|
||||
// Returns the full 3D cartesian extent of the solid.
|
||||
aMin.x = -fDx;
|
||||
aMax.x = fDx;
|
||||
aMin.y = -fDy;
|
||||
aMax.y = fDy;
|
||||
aMin.z = -fDz;
|
||||
aMax.z = fDz;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// GetPointOnSurface
|
||||
//
|
||||
// Return a point (UVector3) randomly and uniformly selected
|
||||
// on the solid surface
|
||||
|
||||
UVector3 UBox::GetPointOnSurface() const
|
||||
{
|
||||
double px, py, pz, select, sumS;
|
||||
double Sxy = fDx * fDy, Sxz = fDx * fDz, Syz = fDy * fDz;
|
||||
|
||||
sumS = Sxy + Sxz + Syz;
|
||||
select = sumS * UUtils::Random();
|
||||
|
||||
if (select < Sxy)
|
||||
{
|
||||
px = -fDx + 2 * fDx * UUtils::Random();
|
||||
py = -fDy + 2 * fDy * UUtils::Random();
|
||||
|
||||
if (UUtils::Random() > 0.5)
|
||||
{
|
||||
pz = fDz;
|
||||
}
|
||||
else
|
||||
{
|
||||
pz = -fDz;
|
||||
}
|
||||
}
|
||||
else if ((select - Sxy) < Sxz)
|
||||
{
|
||||
px = -fDx + 2 * fDx * UUtils::Random();
|
||||
pz = -fDz + 2 * fDz * UUtils::Random();
|
||||
|
||||
if (UUtils::Random() > 0.5)
|
||||
{
|
||||
py = fDy;
|
||||
}
|
||||
else
|
||||
{
|
||||
py = -fDy;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
py = -fDy + 2 * fDy * UUtils::Random();
|
||||
pz = -fDz + 2 * fDz * UUtils::Random();
|
||||
|
||||
if (UUtils::Random() > 0.5)
|
||||
{
|
||||
px = fDx;
|
||||
}
|
||||
else
|
||||
{
|
||||
px = -fDx;
|
||||
}
|
||||
}
|
||||
return UVector3(px, py, pz);
|
||||
}
|
||||
|
||||
std::ostream& UBox::StreamInfo(std::ostream& os) const
|
||||
{
|
||||
int oldprc = os.precision(16);
|
||||
os << "-----------------------------------------------------------\n"
|
||||
<< " *** Dump for solid - " << GetName() << " ***\n"
|
||||
<< " ===================================================\n"
|
||||
<< " Solid type: UBox\n"
|
||||
<< " Parameters: \n"
|
||||
<< " half length X: " << fDx << " mm \n"
|
||||
<< " half length Y: " << fDy << " mm \n"
|
||||
<< " half length Z: " << fDz << " mm \n"
|
||||
<< "-----------------------------------------------------------\n";
|
||||
os.precision(oldprc);
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
void UBox::SetXHalfLength(double dx)
|
||||
{
|
||||
if (dx > 2 * VUSolid::fgTolerance) // limit to thickness of surfaces
|
||||
{
|
||||
fDx = dx;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Dimension X too small for solid: " << GetName() << "!"
|
||||
<< std::endl
|
||||
<< " hX = " << dx;
|
||||
UUtils::Exception("UBox::SetXHalfLength()", "GeomSolids0002",
|
||||
FatalErrorInArguments, 1, message.str().c_str());
|
||||
}
|
||||
fCubicVolume = 0.;
|
||||
fSurfaceArea = 0.;
|
||||
|
||||
}
|
||||
|
||||
void UBox::SetYHalfLength(double dy)
|
||||
{
|
||||
if (dy > 2 * VUSolid::fgTolerance) // limit to thickness of surfaces
|
||||
{
|
||||
fDy = dy;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Dimension Y too small for solid: " << GetName() << "!"
|
||||
<< std::endl
|
||||
<< " hY = " << dy;
|
||||
UUtils::Exception("UBox::SetYHalfLength()", "GeomSolids0002",
|
||||
FatalErrorInArguments, 1, message.str().c_str());
|
||||
}
|
||||
fCubicVolume = 0.;
|
||||
fSurfaceArea = 0.;
|
||||
|
||||
}
|
||||
|
||||
void UBox::SetZHalfLength(double dz)
|
||||
{
|
||||
if (dz > 2 * VUSolid::fgTolerance) // limit to thickness of surfaces
|
||||
{
|
||||
fDz = dz;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Dimension Z too small for solid: " << GetName() << "!"
|
||||
<< std::endl
|
||||
<< " hZ = " << dz;
|
||||
UUtils::Exception("G4Box::SetZHalfLength()", "GeomSolids0002",
|
||||
FatalErrorInArguments, 1, message.str().c_str());
|
||||
}
|
||||
fCubicVolume = 0.;
|
||||
fSurfaceArea = 0.;
|
||||
|
||||
}
|
||||
UGeometryType UBox::GetEntityType() const
|
||||
{
|
||||
return "Box";
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,187 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UEnclosingCylinder
|
||||
//
|
||||
// 19.10.12 Marek Gayer
|
||||
// Created from original implementation in Geant4
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#include "UUtils.hh"
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
#include <sstream>
|
||||
#include "UEnclosingCylinder.hh"
|
||||
#include "UReduciblePolygon.hh"
|
||||
|
||||
#include "VUSolid.hh"
|
||||
#include "UBox.hh"
|
||||
#include "UTubs.hh"
|
||||
|
||||
//
|
||||
// Constructor
|
||||
//
|
||||
UEnclosingCylinder::UEnclosingCylinder(/*const UReduciblePolygon *rz*/double r, double hi, double lo,
|
||||
bool thePhiIsOpen,
|
||||
double theStartPhi,
|
||||
double theTotalPhi)
|
||||
: startPhi(theStartPhi), totalPhi(theTotalPhi),
|
||||
rx1(0.), ry1(0.), dx1(0.), dy1(0.),
|
||||
rx2(0.), ry2(0.), dx2(0.), dy2(0.),
|
||||
concave(theTotalPhi > UUtils::kPi)
|
||||
{
|
||||
//
|
||||
// Obtain largest r and smallest and largest z
|
||||
//
|
||||
|
||||
/*
|
||||
radius = rz->Amax();
|
||||
zHi = rz->Bmax();
|
||||
zLo = rz->Bmin();
|
||||
*/
|
||||
|
||||
radius = r;
|
||||
zHi = hi;
|
||||
zLo = lo;
|
||||
|
||||
double fTolerance = VUSolid::Tolerance();
|
||||
|
||||
tube = new UTubs("", 0, radius + fTolerance, zHi - zLo, theStartPhi, theTotalPhi);
|
||||
|
||||
//
|
||||
// Save phi info
|
||||
//
|
||||
phiIsOpen = thePhiIsOpen;
|
||||
if (phiIsOpen)
|
||||
{
|
||||
rx1 = std::cos(startPhi);
|
||||
ry1 = std::sin(startPhi);
|
||||
dx1 = +ry1 * 10 * fTolerance;
|
||||
dy1 = -rx1 * 10 * fTolerance;
|
||||
|
||||
rx2 = std::cos(startPhi + totalPhi);
|
||||
ry2 = std::sin(startPhi + totalPhi);
|
||||
dx2 = -ry2 * 10 * fTolerance;
|
||||
dy2 = +rx2 * 10 * fTolerance;
|
||||
}
|
||||
|
||||
//
|
||||
// Add safety
|
||||
//
|
||||
radius += 10 * fTolerance;
|
||||
zLo -= 10 * fTolerance;
|
||||
zHi += 10 * fTolerance;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Destructor
|
||||
//
|
||||
UEnclosingCylinder::~UEnclosingCylinder()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Outside
|
||||
//
|
||||
// Decide very rapidly if the point is outside the cylinder
|
||||
//
|
||||
// If one is not certain, return false
|
||||
//
|
||||
bool UEnclosingCylinder::MustBeOutside(const UVector3& p) const
|
||||
{
|
||||
// if (p.Perp() > radius ) return true;
|
||||
if (p.Perp2() > radius * radius) return true;
|
||||
if (p.z < zLo) return true;
|
||||
if (p.z > zHi) return true;
|
||||
|
||||
if (phiIsOpen)
|
||||
{
|
||||
if (concave)
|
||||
{
|
||||
if (((p.x - dx1)*ry1 - (p.y - dy1)*rx1) < 0) return false;
|
||||
if (((p.x - dx2)*ry2 - (p.y - dy2)*rx2) > 0) return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (((p.x - dx1)*ry1 - (p.y - dy1)*rx1) > 0) return true;
|
||||
if (((p.x - dx2)*ry2 - (p.y - dy2)*rx2) < 0) return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Misses
|
||||
//
|
||||
// Decide very rapidly if the trajectory is going to miss the cylinder
|
||||
//
|
||||
// If one is not sure, return false
|
||||
//
|
||||
bool UEnclosingCylinder::ShouldMiss(const UVector3& p,
|
||||
const UVector3& v) const
|
||||
{
|
||||
if (!MustBeOutside(p)) return false;
|
||||
|
||||
// if (p.z < zLo - VUSolid::Tolerance() && v.z <= 0) return true;
|
||||
// if (p.z > zHi + VUSolid::Tolerance() && v.z >= 0) return true;
|
||||
|
||||
double cross = p.x * v.y - p.y * v.x;
|
||||
if (cross > radius) return true;
|
||||
|
||||
double r2 = p.Perp2();
|
||||
if (r2 > radius * radius)
|
||||
{
|
||||
double dot = p.x * v.x + p.y * v.y;
|
||||
if (dot > 0) return true;
|
||||
|
||||
// double n = v.Perp2();
|
||||
// if (Dot < std::sqrt(r2 - radius * radius) * n) return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
if (phiIsOpen)
|
||||
{
|
||||
if (concave)
|
||||
{
|
||||
if ( ((p.x-dx1)*ry1 - (p.y-dy1)*rx1) < 0) return false;
|
||||
if ( ((p.x-dx2)*ry2 - (p.y-dy2)*rx2) > 0) return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( ((p.x-dx1)*ry1 - (p.y-dy1)*rx1) > 0) return true;
|
||||
if ( ((p.x-dx2)*ry2 - (p.y-dy2)*rx2) < 0) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void UEnclosingCylinder::Extent(UVector3& aMin, UVector3& aMax) const
|
||||
{
|
||||
aMin = UVector3(-radius, -radius, zLo);
|
||||
aMax = UVector3(radius, radius, zHi);
|
||||
}
|
||||
|
||||
double UEnclosingCylinder::DistanceTo(const UVector3& p, const UVector3& v) const
|
||||
{
|
||||
return tube->DistanceToIn(p, v);
|
||||
}
|
||||
|
||||
double UEnclosingCylinder::SafetyFromOutside(const UVector3& p) const
|
||||
{
|
||||
return tube->SafetyFromOutside(p);
|
||||
}
|
||||
@@ -0,0 +1,431 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UGenericPolycone
|
||||
//
|
||||
// 19.10.13 Tatiana Nikitina
|
||||
// Created from original implementation in Geant4
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#include "UUtils.hh"
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
#include <sstream>
|
||||
#include "UGenericPolycone.hh"
|
||||
|
||||
#include "UPolyconeSide.hh"
|
||||
#include "UPolyPhiFace.hh"
|
||||
|
||||
|
||||
|
||||
|
||||
#include "UEnclosingCylinder.hh"
|
||||
#include "UReduciblePolygon.hh"
|
||||
|
||||
|
||||
using namespace std;
|
||||
//
|
||||
// Constructor (generic parameters)
|
||||
//
|
||||
UGenericPolycone::UGenericPolycone(const std::string& name,
|
||||
double phiStart,
|
||||
double phiTotal,
|
||||
int numRZ,
|
||||
const double r[],
|
||||
const double z[])
|
||||
: UVCSGfaceted(name)
|
||||
{
|
||||
UReduciblePolygon* rz = new UReduciblePolygon(r, z, numRZ);
|
||||
|
||||
Create(phiStart, phiTotal, rz);
|
||||
|
||||
delete rz;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Create
|
||||
//
|
||||
// Generic create routine, called by each constructor after
|
||||
// conversion of arguments
|
||||
//
|
||||
void UGenericPolycone::Create(double phiStart,
|
||||
double phiTotal,
|
||||
UReduciblePolygon* rz)
|
||||
{
|
||||
//
|
||||
// Perform checks of rz values
|
||||
//
|
||||
if (rz->Amin() < 0.0)
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Illegal input parameters - " << GetName() << std::endl
|
||||
<< " All R values must be >= 0 !";
|
||||
UUtils::Exception("UGenericPolycone::Create()", "GeomSolids0002",
|
||||
FatalErrorInArguments, 1, message.str().c_str());
|
||||
}
|
||||
|
||||
double rzArea = rz->Area();
|
||||
if (rzArea < -VUSolid::Tolerance())
|
||||
rz->ReverseOrder();
|
||||
|
||||
else if (rzArea < -VUSolid::Tolerance())
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Illegal input parameters - " << GetName() << std::endl
|
||||
<< " R/Z Cross section is zero or near zero: " << rzArea;
|
||||
UUtils::Exception("UGenericPolycone::Create()", "GeomSolids0002",
|
||||
FatalErrorInArguments, 1, message.str().c_str());
|
||||
}
|
||||
|
||||
if ((!rz->RemoveDuplicateVertices(VUSolid::Tolerance()))
|
||||
|| (!rz->RemoveRedundantVertices(VUSolid::Tolerance())))
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Illegal input parameters - " << GetName() << std::endl
|
||||
<< " Too few unique R/Z values !";
|
||||
UUtils::Exception("UGenericPolycone::Create()", "GeomSolids0002",
|
||||
FatalErrorInArguments, 1, message.str().c_str());
|
||||
}
|
||||
|
||||
if (rz->CrossesItself(1 / UUtils::kInfinity))
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Illegal input parameters - " << GetName() << std::endl
|
||||
<< " R/Z segments Cross !";
|
||||
UUtils::Exception("UGenericPolycone::Create()", "GeomSolids0002",
|
||||
FatalErrorInArguments, 1, message.str().c_str());
|
||||
}
|
||||
|
||||
numCorner = rz->NumVertices();
|
||||
|
||||
//
|
||||
// Phi opening? Account for some possible roundoff, and interpret
|
||||
// nonsense value as representing no phi opening
|
||||
//
|
||||
if (phiTotal <= 0 || phiTotal > 2 * UUtils::kPi - 1E-10)
|
||||
{
|
||||
phiIsOpen = false;
|
||||
startPhi = 0;
|
||||
endPhi = 2 * UUtils::kPi;
|
||||
}
|
||||
else
|
||||
{
|
||||
phiIsOpen = true;
|
||||
|
||||
//
|
||||
// Convert phi into our convention
|
||||
//
|
||||
startPhi = phiStart;
|
||||
while (startPhi < 0) startPhi += 2 * UUtils::kPi;
|
||||
|
||||
endPhi = phiStart + phiTotal;
|
||||
while (endPhi < startPhi) endPhi += 2 * UUtils::kPi;
|
||||
}
|
||||
|
||||
//
|
||||
// Allocate corner array.
|
||||
//
|
||||
corners = new UPolyconeSideRZ[numCorner];
|
||||
|
||||
//
|
||||
// Copy corners
|
||||
//
|
||||
UReduciblePolygonIterator iterRZ(rz);
|
||||
|
||||
UPolyconeSideRZ* next = corners;
|
||||
iterRZ.Begin();
|
||||
do
|
||||
{
|
||||
next->r = iterRZ.GetA();
|
||||
next->z = iterRZ.GetB();
|
||||
}
|
||||
while (++next, iterRZ.Next());
|
||||
|
||||
//
|
||||
// Allocate face pointer array
|
||||
//
|
||||
numFace = phiIsOpen ? numCorner + 2 : numCorner;
|
||||
faces = new UVCSGface*[numFace];
|
||||
|
||||
//
|
||||
// Construct conical faces
|
||||
//
|
||||
// But! Don't construct a face if both points are at zero radius!
|
||||
//
|
||||
UPolyconeSideRZ* corner = corners,
|
||||
*prev = corners + numCorner - 1,
|
||||
*nextNext;
|
||||
UVCSGface** face = faces;
|
||||
do
|
||||
{
|
||||
next = corner + 1;
|
||||
if (next >= corners + numCorner) next = corners;
|
||||
nextNext = next + 1;
|
||||
if (nextNext >= corners + numCorner) nextNext = corners;
|
||||
|
||||
if (corner->r < 1 / UUtils::kInfinity && next->r < 1 / UUtils::kInfinity) continue;
|
||||
|
||||
//
|
||||
// We must decide here if we can dare declare one of our faces
|
||||
// as having a "valid" normal (i.e. allBehind = true). This
|
||||
// is never possible if the face faces "inward" in r.
|
||||
//
|
||||
bool allBehind;
|
||||
if (corner->z > next->z)
|
||||
{
|
||||
allBehind = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Otherwise, it is only true if the line passing
|
||||
// through the two points of the segment do not
|
||||
// split the r/z Cross section
|
||||
//
|
||||
allBehind = !rz->BisectedBy(corner->r, corner->z,
|
||||
next->r, next->z, VUSolid::Tolerance());
|
||||
}
|
||||
|
||||
*face++ = new UPolyconeSide(prev, corner, next, nextNext,
|
||||
startPhi, endPhi - startPhi, phiIsOpen, allBehind);
|
||||
}
|
||||
while (prev = corner, corner = next, corner > corners);
|
||||
|
||||
if (phiIsOpen)
|
||||
{
|
||||
//
|
||||
// Construct phi open edges
|
||||
//
|
||||
*face++ = new UPolyPhiFace(rz, startPhi, 0, endPhi);
|
||||
*face++ = new UPolyPhiFace(rz, endPhi, 0, startPhi);
|
||||
}
|
||||
|
||||
//
|
||||
// We might have dropped a face or two: recalculate numFace
|
||||
//
|
||||
numFace = face - faces;
|
||||
|
||||
//
|
||||
// Make enclosingCylinder
|
||||
//
|
||||
enclosingCylinder =
|
||||
new UEnclosingCylinder(rz->Amax(), rz->Bmax(), rz->Bmin(), phiIsOpen, phiStart, phiTotal);
|
||||
|
||||
InitVoxels(*rz, enclosingCylinder->radius);
|
||||
|
||||
fNoVoxels = fMaxSection < 2;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Fake default constructor - sets only member data and allocates memory
|
||||
// for usage restricted to object persistency.
|
||||
//
|
||||
|
||||
/*
|
||||
UGenericPolycone::UGenericPolycone( __void__& a )
|
||||
: UVCSGfaceted(a), startPhi(0.), endPhi(0.), phiIsOpen(false),
|
||||
genericPcon(false), numCorner(0), corners(0),
|
||||
fOriginalParameters(0), enclosingCylinder(0)
|
||||
{
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
//
|
||||
// Destructor
|
||||
//
|
||||
UGenericPolycone::~UGenericPolycone()
|
||||
{
|
||||
delete [] corners;
|
||||
delete enclosingCylinder;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Copy constructor
|
||||
//
|
||||
UGenericPolycone::UGenericPolycone(const UGenericPolycone& source)
|
||||
: UVCSGfaceted(source)
|
||||
{
|
||||
CopyStuff(source);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Assignment operator
|
||||
//
|
||||
UGenericPolycone& UGenericPolycone::operator=(const UGenericPolycone& source)
|
||||
{
|
||||
if (this == &source) return *this;
|
||||
|
||||
UVCSGfaceted::operator=(source);
|
||||
|
||||
delete [] corners;
|
||||
|
||||
delete enclosingCylinder;
|
||||
|
||||
CopyStuff(source);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// CopyStuff
|
||||
//
|
||||
void UGenericPolycone::CopyStuff(const UGenericPolycone& source)
|
||||
{
|
||||
//
|
||||
// Simple stuff
|
||||
//
|
||||
startPhi = source.startPhi;
|
||||
endPhi = source.endPhi;
|
||||
phiIsOpen = source.phiIsOpen;
|
||||
numCorner = source.numCorner;
|
||||
|
||||
//
|
||||
// The corner array
|
||||
//
|
||||
corners = new UPolyconeSideRZ[numCorner];
|
||||
|
||||
UPolyconeSideRZ* corn = corners,
|
||||
*sourceCorn = source.corners;
|
||||
do
|
||||
{
|
||||
*corn = *sourceCorn;
|
||||
}
|
||||
while (++sourceCorn, ++corn < corners + numCorner);
|
||||
|
||||
//
|
||||
// Enclosing cylinder
|
||||
//
|
||||
enclosingCylinder = new UEnclosingCylinder(*source.enclosingCylinder);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Reset
|
||||
//
|
||||
bool UGenericPolycone::Reset()
|
||||
{
|
||||
|
||||
std::ostringstream message;
|
||||
message << "Solid " << GetName() << " built using generic construct."
|
||||
<< std::endl << "Not applicable to the generic construct !";
|
||||
// UException("UGenericPolycone::Reset(,,)", "GeomSolids1001",
|
||||
// JustWarning, message, "Parameters NOT resetted.");
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Inside
|
||||
//
|
||||
// This is an override of UVCSGfaceted::Inside, created in order
|
||||
// to speed things up by first checking with UEnclosingCylinder.
|
||||
//
|
||||
VUSolid::EnumInside UGenericPolycone::Inside(const UVector3& p) const
|
||||
{
|
||||
//
|
||||
// Quick test
|
||||
//
|
||||
if (enclosingCylinder->MustBeOutside(p)) return eOutside;
|
||||
|
||||
//
|
||||
// Long answer
|
||||
//
|
||||
return UVCSGfaceted::Inside(p);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// DistanceToIn
|
||||
//
|
||||
// This is an override of UVCSGfaceted::Inside, created in order
|
||||
// to speed things up by first checking with UEnclosingCylinder.
|
||||
//
|
||||
double UGenericPolycone::DistanceToIn(const UVector3& p,
|
||||
const UVector3& v, double aPstep) const
|
||||
{
|
||||
//
|
||||
// Quick test
|
||||
//
|
||||
if (enclosingCylinder->ShouldMiss(p, v))
|
||||
return UUtils::kInfinity;
|
||||
|
||||
//
|
||||
// Long answer
|
||||
//
|
||||
return UVCSGfaceted::DistanceToIn(p, v, aPstep);
|
||||
}
|
||||
|
||||
//
|
||||
// GetEntityType
|
||||
//
|
||||
UGeometryType UGenericPolycone::GetEntityType() const
|
||||
{
|
||||
return std::string("GenericPolycone");
|
||||
}
|
||||
|
||||
//
|
||||
// Make a clone of the object
|
||||
//
|
||||
VUSolid* UGenericPolycone::Clone() const
|
||||
{
|
||||
return new UGenericPolycone(*this);
|
||||
}
|
||||
|
||||
//
|
||||
// Stream object contents to an output stream
|
||||
//
|
||||
std::ostream& UGenericPolycone::StreamInfo(std::ostream& os) const
|
||||
{
|
||||
int oldprc = os.precision(16);
|
||||
os << "-----------------------------------------------------------\n"
|
||||
<< " *** Dump for solid - " << GetName() << " ***\n"
|
||||
<< " ===================================================\n"
|
||||
<< " Solid type: UGenericPolycone\n"
|
||||
<< " Parameters: \n"
|
||||
<< " starting phi angle : " << startPhi / (UUtils::kPi / 180.0) << " degrees \n"
|
||||
<< " ending phi angle : " << endPhi / (UUtils::kPi / 180.0) << " degrees \n";
|
||||
int i = 0;
|
||||
|
||||
os << " number of RZ points: " << numCorner << "\n"
|
||||
<< " RZ values (corners): \n";
|
||||
for (i = 0; i < numCorner; i++)
|
||||
{
|
||||
os << " "
|
||||
<< corners[i].r << ", " << corners[i].z << "\n";
|
||||
}
|
||||
|
||||
os << "-----------------------------------------------------------\n";
|
||||
os.precision(oldprc);
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
//
|
||||
// GetPointOnSurface
|
||||
//
|
||||
UVector3 UGenericPolycone::GetPointOnSurface() const
|
||||
{
|
||||
return GetPointOnSurfaceGeneric();
|
||||
|
||||
}
|
||||
|
||||
void UGenericPolycone::Extent(UVector3& aMin, UVector3& aMax) const
|
||||
{
|
||||
enclosingCylinder->Extent(aMin, aMax);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,512 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UIntersectingCone
|
||||
//
|
||||
// 19.02.13 Marek Gayer
|
||||
// Created from original implementation in Geant4
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#include "UUtils.hh"
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
#include <sstream>
|
||||
#include "UIntersectingCone.hh"
|
||||
#include "VUSolid.hh"
|
||||
|
||||
const double UIntersectingCone::EpsilonQuad = 1.0 / 9.0E99;
|
||||
|
||||
//
|
||||
// Constructor
|
||||
//
|
||||
UIntersectingCone::UIntersectingCone(const double r[2],
|
||||
const double z[2])
|
||||
{
|
||||
static const double halfCarTolerance
|
||||
= 0.5 * VUSolid::Tolerance(); // UGeometryTolerance::GetInstance()->GetSurfaceTolerance();
|
||||
|
||||
//
|
||||
// What type of cone are we?
|
||||
//
|
||||
type1 = (std::fabs(z[1] - z[0]) > std::fabs(r[1] - r[0]));
|
||||
|
||||
if (type1)
|
||||
{
|
||||
B = (r[1] - r[0]) / (z[1] - z[0]); // tube like
|
||||
A = 0.5 * (r[1] + r[0] - B * (z[1] + z[0]));
|
||||
}
|
||||
else
|
||||
{
|
||||
B = (z[1] - z[0]) / (r[1] - r[0]); // disk like
|
||||
A = 0.5 * (z[1] + z[0] - B * (r[1] + r[0]));
|
||||
}
|
||||
//
|
||||
// Calculate extent
|
||||
//
|
||||
if (r[0] < r[1])
|
||||
{
|
||||
rLo = r[0] - halfCarTolerance;
|
||||
rHi = r[1] + halfCarTolerance;
|
||||
}
|
||||
else
|
||||
{
|
||||
rLo = r[1] - halfCarTolerance;
|
||||
rHi = r[0] + halfCarTolerance;
|
||||
}
|
||||
|
||||
if (z[0] < z[1])
|
||||
{
|
||||
zLo = z[0] - halfCarTolerance;
|
||||
zHi = z[1] + halfCarTolerance;
|
||||
}
|
||||
else
|
||||
{
|
||||
zLo = z[1] - halfCarTolerance;
|
||||
zHi = z[0] + halfCarTolerance;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
//
|
||||
// Fake default constructor - sets only member data and allocates memory
|
||||
// for usage restricted to object persistency.
|
||||
//
|
||||
UIntersectingCone::UIntersectingCone( __void__& )
|
||||
: zLo(0.), zHi(0.), rLo(0.), rHi(0.), type1(false), A(0.), B(0.)
|
||||
{
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
//
|
||||
// Destructor
|
||||
//
|
||||
UIntersectingCone::~UIntersectingCone()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// HitOn
|
||||
//
|
||||
// Check r or z extent, as appropriate, to see if the point is possibly
|
||||
// on the cone.
|
||||
//
|
||||
bool UIntersectingCone::HitOn(const double r,
|
||||
const double z)
|
||||
{
|
||||
//
|
||||
// Be careful! The inequalities cannot be "<=" and ">=" here without
|
||||
// punching a tiny hole in our shape!
|
||||
//
|
||||
if (type1)
|
||||
{
|
||||
if (z < zLo || z > zHi) return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (r < rLo || r > rHi) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// LineHitsCone
|
||||
//
|
||||
// Calculate the intersection of a line with our conical surface, ignoring
|
||||
// any phi division
|
||||
//
|
||||
int UIntersectingCone::LineHitsCone(const UVector3& p, const UVector3& v, double& s1, double& s2)
|
||||
{
|
||||
if (type1)
|
||||
{
|
||||
return LineHitsCone1(p, v, s1, s2);
|
||||
}
|
||||
else
|
||||
{
|
||||
return LineHitsCone2(p, v, s1, s2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// LineHitsCone1
|
||||
//
|
||||
// Calculate the intersections of a line with a conical surface. Only
|
||||
// suitable if zPlane[0] != zPlane[1].
|
||||
//
|
||||
// Equation of a line:
|
||||
//
|
||||
// x = x0 + s*tx y = y0 + s*ty z = z0 + s*tz
|
||||
//
|
||||
// Equation of a conical surface:
|
||||
//
|
||||
// x**2 + y**2 = (A + B*z)**2
|
||||
//
|
||||
// Solution is quadratic:
|
||||
//
|
||||
// a*s**2 + b*s + c = 0
|
||||
//
|
||||
// where:
|
||||
//
|
||||
// a = x0**2 + y0**2 - (A + B*z0)**2
|
||||
//
|
||||
// b = 2*( x0*tx + y0*ty - (A*B - B*B*z0)*tz)
|
||||
//
|
||||
// c = tx**2 + ty**2 - (B*tz)**2
|
||||
//
|
||||
// Notice, that if a < 0, this indicates that the two solutions (assuming
|
||||
// they exist) are in opposite cones (that is, given z0 = -A/B, one z < z0
|
||||
// and the other z > z0). For our shapes, the invalid solution is one
|
||||
// which produces A + Bz < 0, or the one where Bz is smallest (most negative).
|
||||
// Since Bz = B*s*tz, if B*tz > 0, we want the largest s, otherwise,
|
||||
// the smaller.
|
||||
//
|
||||
// If there are two solutions on one side of the cone, we want to make
|
||||
// sure that they are on the "correct" side, that is A + B*z0 + s*B*tz >= 0.
|
||||
//
|
||||
// If a = 0, we have a linear problem: s = c/b, which again gives one solution.
|
||||
// This should be rare.
|
||||
//
|
||||
// For b*b - 4*a*c = 0, we also have one solution, which is almost always
|
||||
// a line just grazing the surface of a the cone, which we want to ignore.
|
||||
// However, there are two other, very rare, possibilities:
|
||||
// a line intersecting the z axis and either:
|
||||
// 1. At the same angle std::atan(B) to just miss one side of the cone, or
|
||||
// 2. Intersecting the cone apex (0,0,-A/B)
|
||||
// We *don't* want to miss these! How do we identify them? Well, since
|
||||
// this case is rare, we can at least swallow a little more CPU than we would
|
||||
// normally be comfortable with. Intersection with the z axis means
|
||||
// x0*ty - y0*tx = 0. Case (1) means a==0, and we've already dealt with that
|
||||
// above. Case (2) means a < 0.
|
||||
//
|
||||
// Now: x0*tx + y0*ty = 0 in terms of roundoff error. We can write:
|
||||
// Delta = x0*tx + y0*ty
|
||||
// b = 2*( Delta - (A*B + B*B*z0)*tz )
|
||||
// For:
|
||||
// b*b - 4*a*c = epsilon
|
||||
// where epsilon is small, then:
|
||||
// Delta = epsilon/2/B
|
||||
//
|
||||
|
||||
/*
|
||||
int UIntersectingCone::Solution (const UVector3 &p, const UVector3 &v, double a, double b, double c, double &s1, double &s2)
|
||||
{
|
||||
return 0 || 1 || 2;
|
||||
}
|
||||
*/
|
||||
|
||||
int UIntersectingCone::LineHitsCone1(const UVector3& p, const UVector3& v, double& s1, double& s2)
|
||||
{
|
||||
double x0 = p.x, y0 = p.y, z0 = p.z;
|
||||
double tx = v.x, ty = v.y, tz = v.z;
|
||||
|
||||
double a = tx * tx + ty * ty - UUtils::sqr(B * tz);
|
||||
double b = 2 * (x0 * tx + y0 * ty - (A * B + B * B * z0) * tz);
|
||||
double c = x0 * x0 + y0 * y0 - UUtils::sqr(A + B * z0);
|
||||
|
||||
double radical = b * b - 4 * a * c;
|
||||
double radicalSqrt;
|
||||
|
||||
double minRadical = 1E-6 * std::fabs(b);
|
||||
|
||||
if (radical < -minRadical)
|
||||
{
|
||||
return 0; // No solution
|
||||
}
|
||||
|
||||
if (radical < minRadical)
|
||||
{
|
||||
//
|
||||
// The radical is roughly zero: check for special, very rare, cases
|
||||
//
|
||||
if (std::fabs(a) > EpsilonQuad)
|
||||
{
|
||||
if (B == 0.)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (std::fabs(x0 * ty - y0 * tx) < std::fabs(1E-6 / B))
|
||||
{
|
||||
s1 = -0.5 * b / a;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
radicalSqrt = radical; //TODO: check this case
|
||||
}
|
||||
else
|
||||
{
|
||||
radicalSqrt = std::sqrt(radical);
|
||||
}
|
||||
|
||||
if (a > EpsilonQuad)
|
||||
{
|
||||
double sa, sb, q = -0.5 * (b + (b < 0 ? -radicalSqrt : +radicalSqrt));
|
||||
sa = q / a;
|
||||
sb = c / q;
|
||||
if (sa < sb)
|
||||
{
|
||||
s1 = sa;
|
||||
s2 = sb;
|
||||
}
|
||||
else
|
||||
{
|
||||
s1 = sb;
|
||||
s2 = sa;
|
||||
}
|
||||
if (A + B * (z0 + (s1)*tz) < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
// if ((z0 + (s1)*tz - A)/B < 0) { return 0; } // these lines are equivalent
|
||||
return 2;
|
||||
}
|
||||
else if (a < -EpsilonQuad)
|
||||
{
|
||||
double sa, sb, q = -0.5 * (b + (b < 0 ? -radicalSqrt : +radicalSqrt));
|
||||
sa = q / a;
|
||||
sb = c / q;
|
||||
s1 = (tz * B > 0) ^ (sa > sb) ? sb : sa;
|
||||
return 1;
|
||||
}
|
||||
else if (std::fabs(b) < EpsilonQuad)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
s1 = -c / b;
|
||||
if (A + B * (z0 + (s1)*tz) < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int UIntersectingCone::LineHitsCone1Optimized(const UVector3& p, const UVector3& v, double& s1, double& s2)
|
||||
{
|
||||
double x0 = p.x, y0 = p.y, z0 = p.z;
|
||||
double tx = v.x, ty = v.y, tz = v.z;
|
||||
|
||||
double a = tx * tx + ty * ty - UUtils::sqr(B * tz);
|
||||
double b = 2 * (x0 * tx + y0 * ty - (A * B + B * B * z0) * tz);
|
||||
double c = x0 * x0 + y0 * y0 - UUtils::sqr(A + B * z0);
|
||||
|
||||
double radical = b * b - 4 * a * c;
|
||||
|
||||
double minRadical = 1E-6 * std::fabs(b);
|
||||
|
||||
if (radical < -minRadical)
|
||||
{
|
||||
return 0; // No solution
|
||||
}
|
||||
|
||||
if (std::fabs(a) > EpsilonQuad)
|
||||
{
|
||||
if (radical < minRadical)
|
||||
{
|
||||
//
|
||||
// The radical is roughly zero: check for special, very rare, cases
|
||||
//
|
||||
|
||||
if (B == 0.)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (std::fabs(x0 * ty - y0 * tx) < std::fabs(1E-6 / B))
|
||||
{
|
||||
s1 = -0.5 * b / a;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
double radicalSqrt = std::sqrt(radical);
|
||||
|
||||
if (a > 0)
|
||||
{
|
||||
double sa, sb, q = -0.5 * (b + (b < 0 ? -radicalSqrt : +radicalSqrt));
|
||||
sa = q / a;
|
||||
sb = c / q;
|
||||
if (sa < sb)
|
||||
{
|
||||
s1 = sa;
|
||||
s2 = sb;
|
||||
}
|
||||
else
|
||||
{
|
||||
s1 = sb;
|
||||
s2 = sa;
|
||||
}
|
||||
if (A + B * (z0 + (s1)*tz) < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
// if ((z0 + (s1)*tz - A)/B < 0) { return 0; } // these lines are equivalent
|
||||
return 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
double sa, sb, q = -0.5 * (b + (b < 0 ? -radicalSqrt : +radicalSqrt));
|
||||
sa = q / a;
|
||||
sb = c / q;
|
||||
s1 = (tz * B > 0) ^ (sa > sb) ? sb : sa;
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (std::fabs(b) < EpsilonQuad)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
s1 = -c / b;
|
||||
if (A + B * (z0 + (s1)*tz) < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// LineHitsCone2
|
||||
//
|
||||
// See comments under LineHitsCone1. In this routine, case2, we have:
|
||||
//
|
||||
// Z = A + B*R
|
||||
//
|
||||
// The solution is still quadratic:
|
||||
//
|
||||
// a = tz**2 - B*B*(tx**2 + ty**2)
|
||||
//
|
||||
// b = 2*( (z0-A)*tz - B*B*(x0*tx+y0*ty) )
|
||||
//
|
||||
// c = ( (z0-A)**2 - B*B*(x0**2 + y0**2) )
|
||||
//
|
||||
// The rest is much the same, except some details.
|
||||
//
|
||||
// a > 0 now means we intersect only once in the correct hemisphere.
|
||||
//
|
||||
// a > 0 ? We only want solution which produces R > 0.
|
||||
// since R = (z0+s*tz-A)/B, for tz/B > 0, this is the largest s
|
||||
// for tz/B < 0, this is the smallest s
|
||||
// thus, same as in case 1 ( since sign(tz/B) = sign(tz*B) )
|
||||
//
|
||||
int UIntersectingCone::LineHitsCone2(const UVector3& p,
|
||||
const UVector3& v,
|
||||
double& s1, double& s2)
|
||||
{
|
||||
double x0 = p.x, y0 = p.y, z0 = p.z;
|
||||
double tx = v.x, ty = v.y, tz = v.z;
|
||||
|
||||
// Special case which might not be so rare: B = 0 (precisely)
|
||||
//
|
||||
if (B == 0)
|
||||
{
|
||||
if (std::fabs(tz) < EpsilonQuad)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
s1 = (A - z0) / tz;
|
||||
return 1;
|
||||
}
|
||||
|
||||
double B2 = B * B;
|
||||
|
||||
double a = tz * tz - B2 * (tx * tx + ty * ty);
|
||||
double b = 2 * ((z0 - A) * tz - B2 * (x0 * tx + y0 * ty));
|
||||
double c = UUtils::sqr(z0 - A) - B2 * (x0 * x0 + y0 * y0);
|
||||
|
||||
double radical = b * b - 4 * a * c;
|
||||
|
||||
if (radical < -1E-6 * std::fabs(b))
|
||||
{
|
||||
return 0; // No solution
|
||||
}
|
||||
|
||||
if (radical < 1E-6 * std::fabs(b))
|
||||
{
|
||||
//
|
||||
// The radical is roughly zero: check for special, very rare, cases
|
||||
//
|
||||
if (std::fabs(a) > EpsilonQuad)
|
||||
{
|
||||
if (std::fabs(x0 * ty - y0 * tx) < std::fabs(1E-6 / B))
|
||||
{
|
||||
s1 = -0.5 * b / a;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
radical = std::sqrt(radical);
|
||||
}
|
||||
|
||||
if (a < -EpsilonQuad)
|
||||
{
|
||||
double sa, sb, q = -0.5 * (b + (b < 0 ? -radical : +radical));
|
||||
sa = q / a;
|
||||
sb = c / q;
|
||||
if (sa < sb)
|
||||
{
|
||||
s1 = sa;
|
||||
s2 = sb;
|
||||
}
|
||||
else
|
||||
{
|
||||
s1 = sb;
|
||||
s2 = sa;
|
||||
}
|
||||
if ((z0 + (s1)*tz - A) / B < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
else if (a > EpsilonQuad)
|
||||
{
|
||||
double sa, sb, q = -0.5 * (b + (b < 0 ? -radical : +radical));
|
||||
sa = q / a;
|
||||
sb = c / q;
|
||||
s1 = (tz * B > 0) ^ (sa > sb) ? sb : sa;
|
||||
return 1;
|
||||
}
|
||||
else if (std::fabs(b) < EpsilonQuad)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
s1 = -c / b;
|
||||
if ((z0 + (s1)*tz - A) / B < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,541 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UOrb
|
||||
//
|
||||
// 19.10.12 Marek Gayer
|
||||
// Created from original implementation in Geant4
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
#include "UOrb.hh"
|
||||
#include "UUtils.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
//______________________________________________________________________________
|
||||
UOrb::UOrb(const std::string& name, double r)
|
||||
: VUSolid(name), fR(r), fCubicVolume(0), fSurfaceArea(0)
|
||||
{
|
||||
const double epsilon = 2.e-11; // relative tolerance of fR
|
||||
|
||||
// Check radius
|
||||
//
|
||||
if (r < 10 * VUSolid::fgTolerance) // cartesian tolerance
|
||||
{
|
||||
UUtils::Exception("G4Orb::G4Orb()", "InvalidSetup", FatalErrorInArguments, 1, "Invalid radius > 10*kCarTolerance.");
|
||||
}
|
||||
// VUSolid::fRTolerance is radial tolerance (note: half of G4 tolerance)
|
||||
fRTolerance = max(VUSolid::frTolerance, epsilon * r);
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
/**
|
||||
*
|
||||
* Return whether point inside/outside/on surface
|
||||
* Split into radius checks
|
||||
*
|
||||
* Classify point location with respect to solid:
|
||||
* o eInside - inside the solid
|
||||
* o eSurface - close to surface within tolerance
|
||||
* o eOutside - outside the solid
|
||||
*/
|
||||
// ok
|
||||
VUSolid::EnumInside UOrb::Inside(const UVector3& p) const
|
||||
{
|
||||
double rad2 = p.x * p.x + p.y * p.y + p.z * p.z;
|
||||
// if (false) double rad = sqrt(rad2);
|
||||
|
||||
double tolRMax = fR - fRTolerance * 0.5;
|
||||
|
||||
// Check radial surface
|
||||
double tolRMax2 = tolRMax * tolRMax;
|
||||
if (rad2 <= tolRMax2)
|
||||
return eInside;
|
||||
else
|
||||
{
|
||||
tolRMax = fR + fRTolerance * 0.5;
|
||||
tolRMax2 = tolRMax * tolRMax;
|
||||
if (rad2 <= tolRMax2)
|
||||
return eSurface;
|
||||
else
|
||||
return eOutside;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Computes distance from a point presumably outside the solid to the solid
|
||||
* surface. Ignores first surface if the point is actually inside. Early return
|
||||
* infinity in case the safety to any surface is found greater than the proposed
|
||||
* step aPstep.
|
||||
* The normal vector to the crossed surface is filled only in case the Orb is
|
||||
* crossed, otherwise aNormal.IsNull() is true.
|
||||
*/
|
||||
double UOrb::DistanceToIn(const UVector3& p,
|
||||
const UVector3& v,
|
||||
// UVector3 &aNormal,
|
||||
double /*aPstep*/) const
|
||||
{
|
||||
double snxt = UUtils::kInfinity; // snxt = default return value
|
||||
|
||||
double rad, pDotV3d; // , tolORMax2, tolIRMax2;
|
||||
double c, d2, s = UUtils::kInfinity;
|
||||
|
||||
const double dRmax = 100.*fR;
|
||||
|
||||
// General Precalcs
|
||||
|
||||
rad = sqrt(p.x * p.x + p.y * p.y + p.z * p.z);
|
||||
pDotV3d = p.x * v.x + p.y * v.y + p.z * v.z;
|
||||
|
||||
// Radial Precalcs
|
||||
|
||||
// tolORMax2 = (fR+fRTolerance*0.5)*(fR+fRTolerance*0.5);
|
||||
// tolIRMax2 = (fR-fRTolerance*0.5)*(fR-fRTolerance*0.5);
|
||||
|
||||
// Outer spherical shell intersection
|
||||
// - Only if outside tolerant fR
|
||||
// - Check for if inside and outer G4Orb heading through solid (-> 0)
|
||||
// - No intersect -> no intersection with G4Orb
|
||||
//
|
||||
// Shell eqn: x^2+y^2+z^2 = RSPH^2
|
||||
//
|
||||
// => (px+svx)^2+(py+svy)^2+(pz+svz)^2=R^2
|
||||
//
|
||||
// => (px^2+py^2+pz^2) +2s(pxvx+pyvy+pzvz)+s^2(vx^2+vy^2+vz^2)=R^2
|
||||
// => rad2 +2s(pDotV3d) +s^2 =R^2
|
||||
//
|
||||
// => s=-pDotV3d+-sqrt(pDotV3d^2-(rad2-R^2))
|
||||
|
||||
c = (rad - fR) * (rad + fR); // c = (rad2-R^2))
|
||||
|
||||
if (rad > fR - fRTolerance * 0.5) // not inside in terms of Inside(p)
|
||||
{
|
||||
if (c > fRTolerance * fR)
|
||||
{
|
||||
// If outside tolerant boundary of outer G4Orb in terms of c
|
||||
// [ should be sqrt(rad2) - fR > fRTolerance*0.5 ]
|
||||
|
||||
d2 = pDotV3d * pDotV3d - c;
|
||||
|
||||
if (d2 >= 0)
|
||||
{
|
||||
s = -pDotV3d - sqrt(d2); // ok! = [ ( -2 p dot v) +- sqrt [(-2p dot v)2 - 4*(rad - fR)*(rad + fR)] ] / 2
|
||||
// pDotV3d must be positive always, if not use alternative http://en.wikipedia.org/wiki/Quadratic_equation#Alternative_quadratic_formula
|
||||
if (s >= 0)
|
||||
{
|
||||
if (s > dRmax) // Avoid rounding errors due to precision issues seen on
|
||||
{
|
||||
// 64 bits systems. Split long distances and recompute
|
||||
double fTerm = s - fmod(s, dRmax);
|
||||
s = fTerm + DistanceToIn(p + fTerm * v, v);
|
||||
}
|
||||
return snxt = s;
|
||||
}
|
||||
}
|
||||
else // No intersection with UOrb
|
||||
{
|
||||
return snxt = UUtils::kInfinity;
|
||||
}
|
||||
}
|
||||
else // not outside in terms of c
|
||||
{
|
||||
if (c > -fRTolerance * fR) // on surface
|
||||
{
|
||||
d2 = pDotV3d * pDotV3d - c;
|
||||
if ((d2 < fRTolerance * fR) || (pDotV3d >= 0)) // pDotV3d = cos si >= 0
|
||||
{
|
||||
return snxt = UUtils::kInfinity;
|
||||
}
|
||||
else
|
||||
{
|
||||
return snxt = 0.;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef UDEBUG
|
||||
else // inside ???
|
||||
{
|
||||
UUtils::Exception("UOrb::DistanceToIn(p,v)", "Notification", Warning, 1, "Point p is inside !?");
|
||||
}
|
||||
#endif
|
||||
|
||||
return snxt;
|
||||
}
|
||||
|
||||
double UOrb::DistanceToOutForOutsidePoints(const UVector3& p, const UVector3& v, UVector3& n) const
|
||||
{
|
||||
double distanceIn = DistanceToIn(p, v);
|
||||
UVector3 shift = distanceIn * v;
|
||||
UVector3 surfacePoint = p + shift;
|
||||
UVector3 normal;
|
||||
((UOrb&)*this).Normal(surfacePoint, normal);
|
||||
double dot = normal.Dot(v);
|
||||
if (dot > 0) return 0;
|
||||
else
|
||||
{
|
||||
bool convex;
|
||||
double distanceOut = DistanceToOut(surfacePoint, v, n, convex);
|
||||
return distanceIn + distanceOut;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Computes distance from a point presumably intside the solid to the solid
|
||||
* surface. Ignores first surface along each axis systematically (for points
|
||||
* inside or outside. Early returns zero in case the second surface is behind
|
||||
* the starting point.
|
||||
* o The proposed step is ignored.
|
||||
* o The normal vector to the crossed surface is always filled.
|
||||
* ______________________________________________________________________________
|
||||
*/
|
||||
double UOrb::DistanceToOut(const UVector3& p, const UVector3& v,
|
||||
UVector3& n, bool& convex, double /*aPstep*/) const
|
||||
{
|
||||
double snxt = 0; // snxt: distance to next surface, is default return value
|
||||
bool notOutside = false;
|
||||
convex = true; // orb is always convex, if we leave surface of Orb, we will neber bump on the orb again ...
|
||||
|
||||
double rad2, pDotV3d;
|
||||
double xi, yi, zi; // Intersection point
|
||||
double c, d2;
|
||||
|
||||
rad2 = p.x * p.x + p.y * p.y + p.z * p.z;
|
||||
pDotV3d = p.x * v.x + p.y * v.y + p.z * v.z;
|
||||
|
||||
// Radial Intersection from UOrb::DistanceToIn
|
||||
//
|
||||
// Outer spherical shell intersection
|
||||
// - Only if outside tolerant fR
|
||||
// - Check for if inside and outer UOrb heading through solid (-> 0)
|
||||
// - No intersect -> no intersection with UOrb
|
||||
//
|
||||
// Shell eqn: x^2+y^2+z^2=RSPH^2
|
||||
//
|
||||
// => (px+svx)^2+(py+svy)^2+(pz+svz)^2=R^2
|
||||
//
|
||||
// => (px^2+py^2+pz^2) +2s(pxvx+pyvy+pzvz)+s^2(vx^2+vy^2+vz^2)=R^2
|
||||
// => rad2 +2s(pDotV3d) +s^2 =R^2
|
||||
//
|
||||
// => s=-pDotV3d+-sqrt(pDotV3d^2-(rad2-R^2))
|
||||
|
||||
const double rPlus = fR + fRTolerance;
|
||||
double rad = sqrt(rad2);
|
||||
|
||||
if (rad <= rPlus)
|
||||
{
|
||||
c = (rad - fR) * (rad + fR); // rad2 - fR2
|
||||
|
||||
if (c < fRTolerance * fR)
|
||||
{
|
||||
// Within tolerant Outer radius
|
||||
//
|
||||
// The test is
|
||||
// rad - fR < 0.5*fRTolerance
|
||||
// => rad < fR + 0.5*kRadTol
|
||||
// => rad2 < (fR + 0.5*kRadTol)^2
|
||||
// => rad2 < fR^2 + 2.*0.5*fR*kRadTol + 0.25*kRadTol*kRadTol
|
||||
// => rad2 - fR^2 <~ fR*kRadTol
|
||||
|
||||
d2 = pDotV3d * pDotV3d - c;
|
||||
|
||||
if ((c > -2 * fRTolerance * fR) && // => point is on tolerant surface (i.e. within +- tolerance)
|
||||
((pDotV3d >= 0) || (d2 < 0))) // if (pDotV3d >= 0 ) => leaving outside from Rmax; i.e. from surface
|
||||
// not re-entering
|
||||
// if (d2 < 0) => it means the point is already outside
|
||||
{
|
||||
// if(calcNorm) // NOTE: we do not have this variable, calcNorm is true always
|
||||
{
|
||||
// *validNorm = true; // NOTE: we do not have this variable, probably always true
|
||||
n = UVector3(p.x / fR, p.y / fR, p.z / fR);
|
||||
}
|
||||
return snxt = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we are inside, with + version of quadratic eq. solution we calculate solution for distance
|
||||
snxt = -pDotV3d + sqrt(d2); // second root since inside Rmax
|
||||
// the solution is safe because pDotV3d is negative
|
||||
// c alternative formula, see http://en.wikipedia.org/wiki/Quadratic_equation#Alternative_quadratic_formula
|
||||
// is not neccessary in this case
|
||||
notOutside = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // p is outside ???
|
||||
{
|
||||
// Rule 2: DistanceToOut
|
||||
// Surface points = 0
|
||||
// Outside points: If pointing outwards (dot product with normal positive) return 0, otherwise ignore first surface, another surface should always be on the direction line, use instead distance to this one.
|
||||
|
||||
// double res = DistanceToOutForOutsidePoints(p, v, n);
|
||||
|
||||
cout.precision(16);
|
||||
cout << endl;
|
||||
// DumpInfo();
|
||||
cout << "Position:" << endl << endl;
|
||||
cout << "p.x() = " << p.x << endl;
|
||||
cout << "p.y() = " << p.y << endl;
|
||||
cout << "p.z() = " << p.z << endl << endl;
|
||||
cout << "Rp = " << sqrt(p.x * p.x + p.y * p.y + p.z * p.z) << endl << endl;
|
||||
cout << "Direction:" << endl << endl;
|
||||
cout << "v.x() = " << v.x << endl;
|
||||
cout << "v.y() = " << v.y << endl;
|
||||
cout << "v.z() = " << v.z << endl << endl;
|
||||
cout << "Proposed distance :" << endl << endl;
|
||||
cout << "snxt = " << snxt << endl << endl;
|
||||
|
||||
|
||||
|
||||
cout.precision(6);
|
||||
UUtils::Exception("UOrb::DistanceToOut(p,v,..)", "Notification",
|
||||
Warning, 1, "Logic error: snxt = kInfinity ???");
|
||||
|
||||
}
|
||||
|
||||
// if (calcNorm) // Output switch operator
|
||||
{
|
||||
if (notOutside)
|
||||
{
|
||||
xi = p.x + snxt * v.x; // we move to the point on surface, then return normal at that point which for orb, see method bool UOrb::Normal( const UVector3& p, UVector3 &n)
|
||||
yi = p.y + snxt * v.y;
|
||||
zi = p.z + snxt * v.z;
|
||||
n = UVector3(xi / fR, yi / fR, zi / fR); // we return normalized vector
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
cout.precision(16);
|
||||
cout << endl;
|
||||
// DumpInfo();
|
||||
cout << "Position:" << endl << endl;
|
||||
cout << "p.x() = " << p.x << " mm" << endl;
|
||||
cout << "p.y() = " << p.y << " mm" << endl;
|
||||
cout << "p.z() = " << p.z << " mm" << endl << endl;
|
||||
cout << "Direction:" << endl << endl;
|
||||
cout << "v.x() = " << v.x << endl;
|
||||
cout << "v.y() = " << v.y << endl;
|
||||
cout << "v.z() = " << v.z << endl << endl;
|
||||
cout << "Proposed distance :" << endl << endl;
|
||||
cout << "snxt = " << snxt << " mm" << endl << endl;
|
||||
cout.precision(6);
|
||||
|
||||
|
||||
UUtils::Exception("UOrb::DistanceToOut(p,v,..)", "Notification", Warning, 1, "Undefined side for valid surface normal to solid.");
|
||||
}
|
||||
}
|
||||
return snxt;
|
||||
}
|
||||
|
||||
/*
|
||||
* Estimates the isotropic safety from a point inside the current solid to any
|
||||
* of its surfaces. The algorithm may be accurate or should provide a fast
|
||||
* underestimate.
|
||||
* ______________________________________________________________________________
|
||||
* Note: In geant4, these methods are DistanceToOut, without given direction
|
||||
* Note: ??? Should not Return 0 anymore if point outside, just the value
|
||||
* OK
|
||||
*/
|
||||
double UOrb::SafetyFromInside(const UVector3& p, bool /*aAccurate*/) const
|
||||
{
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Calculate distance (<=actual) to closest surface of shape from inside
|
||||
|
||||
double safe = 0.0, rad = sqrt(p.x * p.x + p.y * p.y + p.z * p.z);
|
||||
|
||||
#ifdef UDEBUG
|
||||
if (Inside(p) == kOutside)
|
||||
{
|
||||
// int oldprc = cout.precision(16);
|
||||
cout << endl;
|
||||
// DumpInfo();
|
||||
cout << "Position:" << endl << endl;
|
||||
cout << "p.x = " << p.x << endl;
|
||||
cout << "p.y = " << p.y << endl;
|
||||
cout << "p.z = " << p.z << endl << endl;
|
||||
// cout.precision(oldprc);
|
||||
UUtils::Exception("UOrb::DistanceToOut(p)", "Notification", Warning, 1,
|
||||
"Point p is outside !?");
|
||||
}
|
||||
#endif
|
||||
|
||||
safe = fR - rad;
|
||||
if (safe < 0.) safe = 0.;
|
||||
return safe;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Estimates the isotropic safety from a point outside the current solid to any
|
||||
* of its surfaces. The algorithm may be accurate or should provide a fast
|
||||
* underestimate.
|
||||
* Note: In geant4, this method is equivalent to DistanceToIn, without given direction
|
||||
* ______________________________________________________________________________
|
||||
*
|
||||
* Calculate distance (<= actual) to closest surface of shape from outside
|
||||
* - Calculate distance to radial plane
|
||||
* - Return 0 if point inside
|
||||
* OK
|
||||
*/
|
||||
double UOrb::SafetyFromOutside(const UVector3& p, bool /*aAccurate*/) const
|
||||
{
|
||||
double safe = 0.0;
|
||||
double rad = sqrt(p.x * p.x + p.y * p.y + p.z * p.z);
|
||||
safe = rad - fR;
|
||||
if (safe < 0)
|
||||
{
|
||||
safe = 0.;
|
||||
}
|
||||
return safe;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Return unit normal of surface closest to p
|
||||
*
|
||||
* From http://lists.trolltech.com/qt-interest/2002-09/thread01124-0.html :
|
||||
* > does anybody here have an algorithm to calculate the normal vector in a
|
||||
* > given point in space (x, y, z) in a sphere? I know that it's not about qt
|
||||
* > but i'll like very mutch the help.
|
||||
* It's simply the connecting vector from the centre of the sphere to the point
|
||||
* (other way around for inward normals) obtained through vector subtraction,
|
||||
* normalized to unity.
|
||||
*
|
||||
* You really should get an algebra book though, as you are bound to encounter
|
||||
* more of these problems in a 3d application.
|
||||
*/
|
||||
bool UOrb::Normal(const UVector3& p, UVector3& n) const
|
||||
{
|
||||
double rad2 = p.x * p.x + p.y * p.y + p.z * p.z;
|
||||
double rad = sqrt(rad2);
|
||||
|
||||
n = UVector3(p.x / rad, p.y / rad, p.z / rad);
|
||||
|
||||
double tolRMaxP = fR + fRTolerance;
|
||||
double tolRMaxM = fR - fRTolerance;
|
||||
|
||||
// Check radial surface
|
||||
bool result = ((rad2 <= tolRMaxP * tolRMaxP) && (rad2 >= tolRMaxM * tolRMaxM)); // means we are on surface
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns extent of the solid along a given cartesian axis
|
||||
* OK
|
||||
*/
|
||||
|
||||
|
||||
void UOrb::Extent(UVector3& aMin, UVector3& aMax) const
|
||||
{
|
||||
aMin.Set(-fR);
|
||||
aMax.Set(fR);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Stream object contents to an output stream
|
||||
|
||||
std::ostream& UOrb::StreamInfo(std::ostream& os) const
|
||||
{
|
||||
int oldprc = os.precision(16);
|
||||
os << "-----------------------------------------------------------\n"
|
||||
<< " *** Dump for solid - " << GetName() << " ***\n"
|
||||
<< " ===================================================\n"
|
||||
<< " Solid type: UOrb\n"
|
||||
<< " Parameters: \n"
|
||||
|
||||
<< " outer radius: " << fR << " mm \n"
|
||||
<< "-----------------------------------------------------------\n";
|
||||
os.precision(oldprc);
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// GetPointOnSurface
|
||||
|
||||
UVector3 UOrb::GetPointOnSurface() const
|
||||
{
|
||||
// generate a random number from zero to 2UUtils::kPi...
|
||||
//
|
||||
double phi = UUtils::Random(0., 2.*UUtils::kPi);
|
||||
double cosphi = std::cos(phi);
|
||||
double sinphi = std::sin(phi);
|
||||
|
||||
// generate a random point uniform in area
|
||||
double costheta = UUtils::Random(-1., 1.);
|
||||
double sintheta = std::sqrt(1. - UUtils::sqr(costheta));
|
||||
|
||||
return UVector3(fR * sintheta * cosphi, fR * sintheta * sinphi, fR * costheta);
|
||||
}
|
||||
|
||||
VUSolid* UOrb:: Clone() const
|
||||
{
|
||||
return new UOrb(GetName(), fR);
|
||||
}
|
||||
|
||||
// Copy constructor
|
||||
|
||||
UOrb::UOrb(const UOrb& rhs)
|
||||
: VUSolid(rhs), fR(rhs.fR), fRTolerance(rhs.fRTolerance), fCubicVolume(rhs.fCubicVolume), fSurfaceArea(rhs.fSurfaceArea)
|
||||
{
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Assignment operator
|
||||
|
||||
UOrb& UOrb::operator = (const UOrb& rhs)
|
||||
{
|
||||
// Check assignment to self
|
||||
//
|
||||
if (this == &rhs)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Copy base class data
|
||||
//
|
||||
VUSolid::operator=(rhs);
|
||||
|
||||
// Copy data
|
||||
//
|
||||
fR = rhs.fR;
|
||||
fRTolerance = rhs.fRTolerance;
|
||||
fCubicVolume = rhs.fCubicVolume;
|
||||
fSurfaceArea = rhs.fSurfaceArea;
|
||||
return *this;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get Parameters List for visualisation
|
||||
|
||||
void UOrb::GetParametersList(int, double* aArray)const
|
||||
{
|
||||
aArray[0] = GetRadius();
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get Entity Type
|
||||
|
||||
UGeometryType UOrb::GetEntityType() const
|
||||
{
|
||||
return "Orb";
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,948 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UPolyhedra
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// To be done:
|
||||
// * Cracks: there are probably small cracks in the seams between the
|
||||
// phi face (UPolyPhiFace) and sides (UPolyhedraSide) that are not
|
||||
// entirely leakproof. Also, I am not sure all vertices are leak proof.
|
||||
// * Many optimizations are possible, but not implemented.
|
||||
// * Visualization needs to be updated outside of this routine.
|
||||
//
|
||||
// Utility classes:
|
||||
// * UEnclosingCylinder: I decided a quick check of geometry would be a
|
||||
// good idea (for CPU speed). If the quick check fails, the regular
|
||||
// full-blown UVCSGfaceted version is invoked.
|
||||
// * UReduciblePolygon: Really meant as a check of input parameters,
|
||||
// this utility class also "converts" the GEANT3-like PGON/PCON
|
||||
// arguments into the newer ones.
|
||||
// Both these classes are implemented outside this file because they are
|
||||
// shared with UPolycone.
|
||||
//
|
||||
// 19.09.13 Marek Gayer
|
||||
// Created from original implementation in Geant4
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#include "UUtils.hh"
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
#include <sstream>
|
||||
|
||||
#include "UPolyhedra.hh"
|
||||
#include "UPolyhedraSide.hh"
|
||||
#include "UPolyPhiFace.hh"
|
||||
#include "UEnclosingCylinder.hh"
|
||||
#include "UReduciblePolygon.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
UPolyhedra::UPolyhedra(const std::string& name,
|
||||
double phiStart,
|
||||
double thePhiTotal,
|
||||
int thefNumSide,
|
||||
int numZPlanes,
|
||||
const double zPlane[],
|
||||
const double rInner[],
|
||||
const double rOuter[])
|
||||
: UVCSGfaceted(name)
|
||||
{
|
||||
Init(phiStart, thePhiTotal, thefNumSide, numZPlanes, zPlane, rInner, rOuter);
|
||||
}
|
||||
|
||||
//
|
||||
// Constructor (GEANT3 style parameters)
|
||||
//
|
||||
// GEANT3 PGON radii are specified in the distance to the norm of each face.
|
||||
//
|
||||
void UPolyhedra::Init(
|
||||
double phiStart,
|
||||
double thePhiTotal,
|
||||
int thefNumSide,
|
||||
int numZPlanes,
|
||||
const double zPlane[],
|
||||
const double rInner[],
|
||||
const double rOuter[])
|
||||
{
|
||||
fGenericPgon = false;
|
||||
|
||||
if (thefNumSide <= 0)
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Solid must have at least one side - " << GetName() << std::endl
|
||||
<< " No sides specified !";
|
||||
UUtils::Exception("UPolyhedra::UPolyhedra()", "GeomSolids0002",
|
||||
FatalErrorInArguments, 1, message.str().c_str());
|
||||
}
|
||||
|
||||
//
|
||||
// Calculate conversion factor from G3 radius to U radius
|
||||
//
|
||||
double phiTotal = thePhiTotal;
|
||||
if ((phiTotal <= 0) || (phiTotal >= 2 * UUtils::kPi * (1 - DBL_EPSILON)))
|
||||
{
|
||||
phiTotal = 2 * UUtils::kPi;
|
||||
}
|
||||
double convertRad = std::cos(0.5 * phiTotal / thefNumSide);
|
||||
|
||||
//
|
||||
// Some historical stuff
|
||||
//
|
||||
// fOriginalParameters = new UPolyhedraHistorical;
|
||||
|
||||
fOriginalParameters.fNumSide = thefNumSide;
|
||||
fOriginalParameters.fStartAngle = phiStart;
|
||||
fOriginalParameters.fOpeningAngle = phiTotal;
|
||||
fOriginalParameters.fNumZPlanes = numZPlanes;
|
||||
fOriginalParameters.fZValues.resize(numZPlanes);
|
||||
fOriginalParameters.Rmin.resize(numZPlanes);
|
||||
fOriginalParameters.Rmax.resize(numZPlanes);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < numZPlanes; i++)
|
||||
{
|
||||
if ((i < numZPlanes - 1) && (zPlane[i] == zPlane[i + 1]))
|
||||
{
|
||||
if ((rInner[i] > rOuter[i + 1])
|
||||
|| (rInner[i + 1] > rOuter[i]))
|
||||
{
|
||||
|
||||
std::ostringstream message;
|
||||
message << "Cannot create a Polyhedra with no contiguous segments."
|
||||
<< std::endl
|
||||
<< " Segments are not contiguous !" << std::endl
|
||||
<< " rMin[" << i << "] = " << rInner[i]
|
||||
<< " -- rMax[" << i + 1 << "] = " << rOuter[i + 1] << std::endl
|
||||
<< " rMin[" << i + 1 << "] = " << rInner[i + 1]
|
||||
<< " -- rMax[" << i << "] = " << rOuter[i];
|
||||
UUtils::Exception("UPolyhedra::UPolyhedra()", "GeomSolids0002",
|
||||
FatalErrorInArguments, 1, message.str().c_str());
|
||||
}
|
||||
}
|
||||
fOriginalParameters.fZValues[i] = zPlane[i];
|
||||
fOriginalParameters.Rmin[i] = rInner[i] / convertRad;
|
||||
fOriginalParameters.Rmax[i] = rOuter[i] / convertRad;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Build RZ polygon using special PCON/PGON GEANT3 constructor
|
||||
//
|
||||
UReduciblePolygon* rz =
|
||||
new UReduciblePolygon(rInner, rOuter, zPlane, numZPlanes);
|
||||
rz->ScaleA(1 / convertRad);
|
||||
|
||||
//
|
||||
// Do the real work
|
||||
//
|
||||
Create(phiStart, phiTotal, thefNumSide, rz);
|
||||
|
||||
delete rz;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Constructor (generic parameters)
|
||||
//
|
||||
UPolyhedra::UPolyhedra(const std::string& name,
|
||||
double phiStart,
|
||||
double phiTotal,
|
||||
int thefNumSide,
|
||||
int numRZ,
|
||||
const double r[],
|
||||
const double z[])
|
||||
: UVCSGfaceted(name), fGenericPgon(true)
|
||||
{
|
||||
UReduciblePolygon* rz = new UReduciblePolygon(r, z, numRZ);
|
||||
|
||||
Create(phiStart, phiTotal, thefNumSide, rz);
|
||||
|
||||
// Set fOriginalParameters struct for consistency
|
||||
//
|
||||
SetOriginalParameters();
|
||||
|
||||
delete rz;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Create
|
||||
//
|
||||
// Generic create routine, called by each constructor
|
||||
// after conversion of arguments
|
||||
//
|
||||
void UPolyhedra::Create(double phiStart,
|
||||
double phiTotal,
|
||||
int thefNumSide,
|
||||
UReduciblePolygon* rz)
|
||||
{
|
||||
//
|
||||
// Perform checks of rz values
|
||||
//
|
||||
if (rz->Amin() < 0.0)
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Illegal input parameters - " << GetName() << std::endl
|
||||
<< " All R values must be >= 0 !";
|
||||
UUtils::Exception("UPolyhedra::Create()", "GeomSolids0002",
|
||||
FatalErrorInArguments, 1, message.str().c_str());
|
||||
}
|
||||
|
||||
double rzArea = rz->Area();
|
||||
if (rzArea < -VUSolid::Tolerance())
|
||||
rz->ReverseOrder();
|
||||
|
||||
else if (rzArea < -VUSolid::Tolerance())
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Illegal input parameters - " << GetName() << std::endl
|
||||
<< " R/Z Cross section is zero or near zero: " << rzArea;
|
||||
UUtils::Exception("UPolyhedra::Create()", "GeomSolids0002",
|
||||
FatalErrorInArguments, 1, message.str().c_str());
|
||||
}
|
||||
|
||||
if ((!rz->RemoveDuplicateVertices(VUSolid::Tolerance()))
|
||||
|| (!rz->RemoveRedundantVertices(VUSolid::Tolerance())))
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Illegal input parameters - " << GetName() << std::endl
|
||||
<< " Too few unique R/Z values !";
|
||||
UUtils::Exception("UPolyhedra::Create()", "GeomSolids0002",
|
||||
FatalErrorInArguments, 1, message.str().c_str());
|
||||
}
|
||||
|
||||
if (rz->CrossesItself(1 / UUtils::kInfinity))
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Illegal input parameters - " << GetName() << std::endl
|
||||
<< " R/Z segments Cross !";
|
||||
UUtils::Exception("UPolyhedra::Create()", "GeomSolids0002",
|
||||
FatalErrorInArguments, 1, message.str().c_str());
|
||||
}
|
||||
|
||||
fNumCorner = rz->NumVertices();
|
||||
|
||||
fStartPhi = phiStart;
|
||||
while (fStartPhi < 0) fStartPhi += 2 * UUtils::kPi;
|
||||
//
|
||||
// Phi opening? Account for some possible roundoff, and interpret
|
||||
// nonsense value as representing no phi opening
|
||||
//
|
||||
if ((phiTotal <= 0) || (phiTotal > 2 * UUtils::kPi * (1 - DBL_EPSILON)))
|
||||
{
|
||||
fPhiIsOpen = false;
|
||||
fEndPhi = phiStart + 2 * UUtils::kPi;
|
||||
}
|
||||
else
|
||||
{
|
||||
fPhiIsOpen = true;
|
||||
|
||||
//
|
||||
// Convert phi into our convention
|
||||
//
|
||||
fEndPhi = phiStart + phiTotal;
|
||||
while (fEndPhi < fStartPhi) fEndPhi += 2 * UUtils::kPi;
|
||||
}
|
||||
|
||||
//
|
||||
// Save number sides
|
||||
//
|
||||
fNumSides = thefNumSide;
|
||||
|
||||
//
|
||||
// Allocate corner array.
|
||||
//
|
||||
fCorners = new UPolyhedraSideRZ[fNumCorner];
|
||||
|
||||
//
|
||||
// Copy fCorners
|
||||
//
|
||||
UReduciblePolygonIterator iterRZ(rz);
|
||||
|
||||
UPolyhedraSideRZ* next = fCorners;
|
||||
iterRZ.Begin();
|
||||
do
|
||||
{
|
||||
next->r = iterRZ.GetA();
|
||||
next->z = iterRZ.GetB();
|
||||
}
|
||||
while (++next, iterRZ.Next());
|
||||
|
||||
//
|
||||
// Allocate face pointer array
|
||||
//
|
||||
numFace = fPhiIsOpen ? fNumCorner + 2 : fNumCorner;
|
||||
faces = new UVCSGface*[numFace];
|
||||
|
||||
//
|
||||
// Construct side faces
|
||||
//
|
||||
// To do so properly, we need to keep track of four successive RZ
|
||||
// fCorners.
|
||||
//
|
||||
// But! Don't construct a face if both points are at zero radius!
|
||||
|
||||
//
|
||||
UPolyhedraSideRZ* corner = fCorners,
|
||||
*prev = fCorners + fNumCorner - 1,
|
||||
*nextNext;
|
||||
UVCSGface** face = faces;
|
||||
do
|
||||
{
|
||||
next = corner + 1;
|
||||
if (next >= fCorners + fNumCorner) next = fCorners;
|
||||
nextNext = next + 1;
|
||||
if (nextNext >= fCorners + fNumCorner) nextNext = fCorners;
|
||||
|
||||
if (corner->r < 1 / UUtils::kInfinity && next->r < 1 / UUtils::kInfinity) continue;
|
||||
/*
|
||||
// We must decide here if we can dare declare one of our faces
|
||||
// as having a "valid" normal (i.e. allBehind = true). This
|
||||
// is never possible if the face faces "inward" in r *unless*
|
||||
// we have only one side
|
||||
//
|
||||
bool allBehind;
|
||||
if ((corner->z > next->z) && (fNumSides > 1))
|
||||
{
|
||||
allBehind = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Otherwise, it is only true if the line passing
|
||||
// through the two points of the segment do not
|
||||
// split the r/z Cross section
|
||||
//
|
||||
allBehind = !rz->BisectedBy( corner->r, corner->z,
|
||||
next->r, next->z, VUSolid::Tolerance() );
|
||||
}
|
||||
*/
|
||||
*face++ = new UPolyhedraSide(prev, corner, next, nextNext,
|
||||
fNumSides, fStartPhi, fEndPhi - fStartPhi, fPhiIsOpen);
|
||||
}
|
||||
while (prev = corner, corner = next, corner > fCorners);
|
||||
|
||||
if (fPhiIsOpen)
|
||||
{
|
||||
//
|
||||
// Construct phi open edges
|
||||
//
|
||||
*face++ = new UPolyPhiFace(rz, fStartPhi, phiTotal / fNumSides, fEndPhi);
|
||||
*face++ = new UPolyPhiFace(rz, fEndPhi, phiTotal / fNumSides, fStartPhi);
|
||||
}
|
||||
|
||||
//
|
||||
// We might have dropped a face or two: recalculate numFace
|
||||
//
|
||||
numFace = face - faces;
|
||||
|
||||
//
|
||||
// Make fEnclosingCylinder
|
||||
//
|
||||
|
||||
/*
|
||||
double mxy = rz->Amax();
|
||||
double alfa = UUtils::kPi / fNumSides;
|
||||
|
||||
double r= rz->Amax();
|
||||
|
||||
if (fNumSides != 0)
|
||||
{
|
||||
// mxy *= std::sqrt(2.0); // this is old and wrong, works only for n = 4
|
||||
double k = std::tan(alfa) * mxy;
|
||||
double l = mxy / std::cos(alfa);
|
||||
mxy = l;
|
||||
r = l;
|
||||
}
|
||||
mxy += fgTolerance;
|
||||
*/
|
||||
|
||||
fEnclosingCylinder =
|
||||
new UEnclosingCylinder(rz->Amax(), rz->Bmax(), rz->Bmin(), fPhiIsOpen, phiStart, phiTotal);
|
||||
|
||||
InitVoxels(*rz, fEnclosingCylinder->radius);
|
||||
|
||||
fNoVoxels = fMaxSection < 2; // minimally, sections with at least numbers 0,1,2 values required, this corresponds to fMaxSection == 2
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Destructor
|
||||
//
|
||||
UPolyhedra::~UPolyhedra()
|
||||
{
|
||||
delete [] fCorners;
|
||||
// if (fOriginalParameters) delete fOriginalParameters;
|
||||
|
||||
delete fEnclosingCylinder;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Copy constructor
|
||||
//
|
||||
UPolyhedra::UPolyhedra(const UPolyhedra& source)
|
||||
: UVCSGfaceted(source)
|
||||
{
|
||||
CopyStuff(source);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Assignment operator
|
||||
//
|
||||
UPolyhedra& UPolyhedra::operator=(const UPolyhedra& source)
|
||||
{
|
||||
if (this == &source) return *this;
|
||||
|
||||
UVCSGfaceted::operator=(source);
|
||||
|
||||
delete [] fCorners;
|
||||
// if (fOriginalParameters) delete fOriginalParameters;
|
||||
|
||||
delete fEnclosingCylinder;
|
||||
|
||||
CopyStuff(source);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// CopyStuff
|
||||
//
|
||||
void UPolyhedra::CopyStuff(const UPolyhedra& source)
|
||||
{
|
||||
//
|
||||
// Simple stuff
|
||||
//
|
||||
fNumSides = source.fNumSides;
|
||||
fStartPhi = source.fStartPhi;
|
||||
fEndPhi = source.fEndPhi;
|
||||
fPhiIsOpen = source.fPhiIsOpen;
|
||||
fNumCorner = source.fNumCorner;
|
||||
fGenericPgon = source.fGenericPgon;
|
||||
|
||||
//
|
||||
// The corner array
|
||||
//
|
||||
fCorners = new UPolyhedraSideRZ[fNumCorner];
|
||||
|
||||
UPolyhedraSideRZ* corn = fCorners,
|
||||
*sourceCorn = source.fCorners;
|
||||
do
|
||||
{
|
||||
*corn = *sourceCorn;
|
||||
}
|
||||
while (++sourceCorn, ++corn < fCorners + fNumCorner);
|
||||
|
||||
fOriginalParameters = source.fOriginalParameters;
|
||||
|
||||
//
|
||||
// Enclosing cylinder
|
||||
//
|
||||
fEnclosingCylinder = new UEnclosingCylinder(*source.fEnclosingCylinder);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Reset
|
||||
//
|
||||
// Recalculates and reshapes the solid, given pre-assigned scaled
|
||||
// fOriginalParameters.
|
||||
//
|
||||
bool UPolyhedra::Reset()
|
||||
{
|
||||
if (fGenericPgon)
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Solid " << GetName() << " built using generic construct."
|
||||
<< std::endl << "Not applicable to the generic construct !";
|
||||
UUtils::Exception("UPolyhedra::Reset(,,)", "GeomSolids1001",
|
||||
Warning, 1, message.str().c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
//
|
||||
// Clear old setup
|
||||
//
|
||||
UVCSGfaceted::DeleteStuff();
|
||||
delete [] fCorners;
|
||||
delete fEnclosingCylinder;
|
||||
|
||||
//
|
||||
// Rebuild polyhedra
|
||||
//
|
||||
UReduciblePolygon* rz =
|
||||
new UReduciblePolygon(&fOriginalParameters.Rmin[0],
|
||||
&fOriginalParameters.Rmax[0],
|
||||
&fOriginalParameters.fZValues[0],
|
||||
fOriginalParameters.fNumZPlanes);
|
||||
Create(fOriginalParameters.fStartAngle,
|
||||
fOriginalParameters.fOpeningAngle,
|
||||
fOriginalParameters.fNumSide, rz);
|
||||
delete rz;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Inside
|
||||
//
|
||||
// This is an override of UVCSGfaceted::Inside, created in order
|
||||
// to speed things up by first checking with UEnclosingCylinder.
|
||||
//
|
||||
VUSolid::EnumInside UPolyhedra::Inside(const UVector3& p) const
|
||||
{
|
||||
//
|
||||
// Quick test
|
||||
//
|
||||
if (fEnclosingCylinder->MustBeOutside(p)) return eOutside;
|
||||
|
||||
//
|
||||
// Long answer
|
||||
//
|
||||
return UVCSGfaceted::Inside(p);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// DistanceToIn
|
||||
//
|
||||
double UPolyhedra::SafetyFromOutside(const UVector3& aPoint, bool aAccurate) const
|
||||
{
|
||||
return UVCSGfaceted::SafetyFromOutside(aPoint, aAccurate);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// GetEntityType
|
||||
//
|
||||
UGeometryType UPolyhedra::GetEntityType() const
|
||||
{
|
||||
return std::string("Polyhedra");
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Make a clone of the object
|
||||
//
|
||||
VUSolid* UPolyhedra::Clone() const
|
||||
{
|
||||
return new UPolyhedra(*this);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Stream object contents to an output stream
|
||||
//
|
||||
std::ostream& UPolyhedra::StreamInfo(std::ostream& os) const
|
||||
{
|
||||
int oldprc = os.precision(16);
|
||||
os << "-----------------------------------------------------------\n"
|
||||
<< " *** Dump for solid - " << GetName() << " ***\n"
|
||||
<< " ===================================================\n"
|
||||
<< " Solid type: UPolyhedra\n"
|
||||
<< " Parameters: \n"
|
||||
<< " starting phi angle : " << fStartPhi / (UUtils::kPi / 180.0) << " degrees \n"
|
||||
<< " ending phi angle : " << fEndPhi / (UUtils::kPi / 180.0) << " degrees \n";
|
||||
int i = 0;
|
||||
if (!fGenericPgon)
|
||||
{
|
||||
int numPlanes = fOriginalParameters.fNumZPlanes;
|
||||
os << " number of Z planes: " << numPlanes << "\n"
|
||||
<< " Z values: \n";
|
||||
for (i = 0; i < numPlanes; i++)
|
||||
{
|
||||
os << " Z plane " << i << ": "
|
||||
<< fOriginalParameters.fZValues[i] << "\n";
|
||||
}
|
||||
os << " Tangent distances to inner surface (Rmin): \n";
|
||||
for (i = 0; i < numPlanes; i++)
|
||||
{
|
||||
os << " Z plane " << i << ": "
|
||||
<< fOriginalParameters.Rmin[i] << "\n";
|
||||
}
|
||||
os << " Tangent distances to outer surface (Rmax): \n";
|
||||
for (i = 0; i < numPlanes; i++)
|
||||
{
|
||||
os << " Z plane " << i << ": "
|
||||
<< fOriginalParameters.Rmax[i] << "\n";
|
||||
}
|
||||
}
|
||||
os << " number of RZ points: " << fNumCorner << "\n"
|
||||
<< " RZ values (fCorners): \n";
|
||||
for (i = 0; i < fNumCorner; i++)
|
||||
{
|
||||
os << " "
|
||||
<< fCorners[i].r << ", " << fCorners[i].z << "\n";
|
||||
}
|
||||
os << "-----------------------------------------------------------\n";
|
||||
os.precision(oldprc);
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// GetPointOnPlane
|
||||
//
|
||||
// Auxiliary method for get point on surface
|
||||
//
|
||||
UVector3 UPolyhedra::GetPointOnPlane(UVector3 p0, UVector3 p1,
|
||||
UVector3 p2, UVector3 p3) const
|
||||
{
|
||||
double lambda1, lambda2, chose, aOne, aTwo;
|
||||
UVector3 t, u, v, w, Area, normal;
|
||||
aOne = 1.;
|
||||
aTwo = 1.;
|
||||
|
||||
t = p1 - p0;
|
||||
u = p2 - p1;
|
||||
v = p3 - p2;
|
||||
w = p0 - p3;
|
||||
|
||||
chose = UUtils::Random(0., aOne + aTwo);
|
||||
if ((chose >= 0.) && (chose < aOne))
|
||||
{
|
||||
lambda1 = UUtils::Random(0., 1.);
|
||||
lambda2 = UUtils::Random(0., lambda1);
|
||||
return (p2 + lambda1 * v + lambda2 * w);
|
||||
}
|
||||
|
||||
lambda1 = UUtils::Random(0., 1.);
|
||||
lambda2 = UUtils::Random(0., lambda1);
|
||||
return (p0 + lambda1 * t + lambda2 * u);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// GetPointOnTriangle
|
||||
//
|
||||
// Auxiliary method for get point on surface
|
||||
//
|
||||
UVector3 UPolyhedra::GetPointOnTriangle(UVector3 p1,
|
||||
UVector3 p2,
|
||||
UVector3 p3) const
|
||||
{
|
||||
double lambda1, lambda2;
|
||||
UVector3 v = p3 - p1, w = p1 - p2;
|
||||
|
||||
lambda1 = UUtils::Random(0., 1.);
|
||||
lambda2 = UUtils::Random(0., lambda1);
|
||||
|
||||
return (p2 + lambda1 * w + lambda2 * v);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// GetPointOnSurface
|
||||
//
|
||||
UVector3 UPolyhedra::GetPointOnSurface() const
|
||||
{
|
||||
if (!fGenericPgon) // Polyhedra by faces
|
||||
{
|
||||
int j, numPlanes = fOriginalParameters.fNumZPlanes, Flag = 0;
|
||||
double chose, totArea = 0., Achose1, Achose2,
|
||||
rad1, rad2, sinphi1, sinphi2, cosphi1, cosphi2;
|
||||
double a, b, l2, rang, totalPhi, ksi,
|
||||
area, aTop = 0., aBottom = 0., zVal = 0.;
|
||||
|
||||
UVector3 p0, p1, p2, p3;
|
||||
std::vector<double> aVector1;
|
||||
std::vector<double> aVector2;
|
||||
std::vector<double> aVector3;
|
||||
|
||||
totalPhi = (fPhiIsOpen) ? (fEndPhi - fStartPhi) : 2 * UUtils::kPi;
|
||||
ksi = totalPhi / fNumSides;
|
||||
double cosksi = std::cos(ksi / 2.);
|
||||
|
||||
// Below we generate the areas relevant to our solid
|
||||
//
|
||||
for (j = 0; j < numPlanes - 1; j++)
|
||||
{
|
||||
a = fOriginalParameters.Rmax[j + 1];
|
||||
b = fOriginalParameters.Rmax[j];
|
||||
l2 = UUtils::sqr(fOriginalParameters.fZValues[j]
|
||||
- fOriginalParameters.fZValues[j + 1]) + UUtils::sqr(b - a);
|
||||
area = std::sqrt(l2 - UUtils::sqr((a - b) * cosksi)) * (a + b) * cosksi;
|
||||
aVector1.push_back(area);
|
||||
}
|
||||
|
||||
for (j = 0; j < numPlanes - 1; j++)
|
||||
{
|
||||
a = fOriginalParameters.Rmin[j + 1]; //*cosksi;
|
||||
b = fOriginalParameters.Rmin[j];//*cosksi;
|
||||
l2 = UUtils::sqr(fOriginalParameters.fZValues[j]
|
||||
- fOriginalParameters.fZValues[j + 1]) + UUtils::sqr(b - a);
|
||||
area = std::sqrt(l2 - UUtils::sqr((a - b) * cosksi)) * (a + b) * cosksi;
|
||||
aVector2.push_back(area);
|
||||
}
|
||||
|
||||
for (j = 0; j < numPlanes - 1; j++)
|
||||
{
|
||||
if (fPhiIsOpen == true)
|
||||
{
|
||||
aVector3.push_back(0.5 * (fOriginalParameters.Rmax[j]
|
||||
- fOriginalParameters.Rmin[j]
|
||||
+ fOriginalParameters.Rmax[j + 1]
|
||||
- fOriginalParameters.Rmin[j + 1])
|
||||
*std::fabs(fOriginalParameters.fZValues[j + 1]
|
||||
- fOriginalParameters.fZValues[j]));
|
||||
}
|
||||
else
|
||||
{
|
||||
aVector3.push_back(0.);
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0; j < numPlanes - 1; j++)
|
||||
{
|
||||
totArea += fNumSides * (aVector1[j] + aVector2[j]) + 2.*aVector3[j];
|
||||
}
|
||||
|
||||
// Must include top and bottom areas
|
||||
//
|
||||
if (fOriginalParameters.Rmax[numPlanes - 1] != 0.)
|
||||
{
|
||||
a = fOriginalParameters.Rmax[numPlanes - 1];
|
||||
b = fOriginalParameters.Rmin[numPlanes - 1];
|
||||
l2 = UUtils::sqr(a - b);
|
||||
aTop = std::sqrt(l2 - UUtils::sqr((a - b) * cosksi)) * (a + b) * cosksi;
|
||||
}
|
||||
|
||||
if (fOriginalParameters.Rmax[0] != 0.)
|
||||
{
|
||||
a = fOriginalParameters.Rmax[0];
|
||||
b = fOriginalParameters.Rmin[0];
|
||||
l2 = UUtils::sqr(a - b);
|
||||
aBottom = std::sqrt(l2 - UUtils::sqr((a - b) * cosksi)) * (a + b) * cosksi;
|
||||
}
|
||||
|
||||
Achose1 = 0.;
|
||||
Achose2 = fNumSides * (aVector1[0] + aVector2[0]) + 2.*aVector3[0];
|
||||
|
||||
chose = UUtils::Random(0., totArea + aTop + aBottom);
|
||||
if ((chose >= 0.) && (chose < aTop + aBottom))
|
||||
{
|
||||
chose = UUtils::Random(fStartPhi, fStartPhi + totalPhi);
|
||||
rang = std::floor((chose - fStartPhi) / ksi - 0.01);
|
||||
if (rang < 0)
|
||||
{
|
||||
rang = 0;
|
||||
}
|
||||
rang = std::fabs(rang);
|
||||
sinphi1 = std::sin(fStartPhi + rang * ksi);
|
||||
sinphi2 = std::sin(fStartPhi + (rang + 1) * ksi);
|
||||
cosphi1 = std::cos(fStartPhi + rang * ksi);
|
||||
cosphi2 = std::cos(fStartPhi + (rang + 1) * ksi);
|
||||
chose = UUtils::Random(0., aTop + aBottom);
|
||||
if (chose >= 0. && chose < aTop)
|
||||
{
|
||||
rad1 = fOriginalParameters.Rmin[numPlanes - 1];
|
||||
rad2 = fOriginalParameters.Rmax[numPlanes - 1];
|
||||
zVal = fOriginalParameters.fZValues[numPlanes - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
rad1 = fOriginalParameters.Rmin[0];
|
||||
rad2 = fOriginalParameters.Rmax[0];
|
||||
zVal = fOriginalParameters.fZValues[0];
|
||||
}
|
||||
p0 = UVector3(rad1 * cosphi1, rad1 * sinphi1, zVal);
|
||||
p1 = UVector3(rad2 * cosphi1, rad2 * sinphi1, zVal);
|
||||
p2 = UVector3(rad2 * cosphi2, rad2 * sinphi2, zVal);
|
||||
p3 = UVector3(rad1 * cosphi2, rad1 * sinphi2, zVal);
|
||||
return GetPointOnPlane(p0, p1, p2, p3);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (j = 0; j < numPlanes - 1; j++)
|
||||
{
|
||||
if (((chose >= Achose1) && (chose < Achose2)) || (j == numPlanes - 2))
|
||||
{
|
||||
Flag = j;
|
||||
break;
|
||||
}
|
||||
Achose1 += fNumSides * (aVector1[j] + aVector2[j]) + 2.*aVector3[j];
|
||||
Achose2 = Achose1 + fNumSides * (aVector1[j + 1] + aVector2[j + 1])
|
||||
+ 2.*aVector3[j + 1];
|
||||
}
|
||||
}
|
||||
|
||||
// At this point we have chosen a subsection
|
||||
// between to adjacent plane cuts...
|
||||
|
||||
j = Flag;
|
||||
|
||||
totArea = fNumSides * (aVector1[j] + aVector2[j]) + 2.*aVector3[j];
|
||||
chose = UUtils::Random(0., totArea);
|
||||
|
||||
if ((chose >= 0.) && (chose < fNumSides * aVector1[j]))
|
||||
{
|
||||
chose = UUtils::Random(fStartPhi, fStartPhi + totalPhi);
|
||||
rang = std::floor((chose - fStartPhi) / ksi - 0.01);
|
||||
if (rang < 0)
|
||||
{
|
||||
rang = 0;
|
||||
}
|
||||
rang = std::fabs(rang);
|
||||
rad1 = fOriginalParameters.Rmax[j];
|
||||
rad2 = fOriginalParameters.Rmax[j + 1];
|
||||
sinphi1 = std::sin(fStartPhi + rang * ksi);
|
||||
sinphi2 = std::sin(fStartPhi + (rang + 1) * ksi);
|
||||
cosphi1 = std::cos(fStartPhi + rang * ksi);
|
||||
cosphi2 = std::cos(fStartPhi + (rang + 1) * ksi);
|
||||
zVal = fOriginalParameters.fZValues[j];
|
||||
|
||||
p0 = UVector3(rad1 * cosphi1, rad1 * sinphi1, zVal);
|
||||
p1 = UVector3(rad1 * cosphi2, rad1 * sinphi2, zVal);
|
||||
|
||||
zVal = fOriginalParameters.fZValues[j + 1];
|
||||
|
||||
p2 = UVector3(rad2 * cosphi2, rad2 * sinphi2, zVal);
|
||||
p3 = UVector3(rad2 * cosphi1, rad2 * sinphi1, zVal);
|
||||
return GetPointOnPlane(p0, p1, p2, p3);
|
||||
}
|
||||
else if ((chose >= fNumSides * aVector1[j])
|
||||
&& (chose <= fNumSides * (aVector1[j] + aVector2[j])))
|
||||
{
|
||||
chose = UUtils::Random(fStartPhi, fStartPhi + totalPhi);
|
||||
rang = std::floor((chose - fStartPhi) / ksi - 0.01);
|
||||
if (rang < 0)
|
||||
{
|
||||
rang = 0;
|
||||
}
|
||||
rang = std::fabs(rang);
|
||||
rad1 = fOriginalParameters.Rmin[j];
|
||||
rad2 = fOriginalParameters.Rmin[j + 1];
|
||||
sinphi1 = std::sin(fStartPhi + rang * ksi);
|
||||
sinphi2 = std::sin(fStartPhi + (rang + 1) * ksi);
|
||||
cosphi1 = std::cos(fStartPhi + rang * ksi);
|
||||
cosphi2 = std::cos(fStartPhi + (rang + 1) * ksi);
|
||||
zVal = fOriginalParameters.fZValues[j];
|
||||
|
||||
p0 = UVector3(rad1 * cosphi1, rad1 * sinphi1, zVal);
|
||||
p1 = UVector3(rad1 * cosphi2, rad1 * sinphi2, zVal);
|
||||
|
||||
zVal = fOriginalParameters.fZValues[j + 1];
|
||||
|
||||
p2 = UVector3(rad2 * cosphi2, rad2 * sinphi2, zVal);
|
||||
p3 = UVector3(rad2 * cosphi1, rad2 * sinphi1, zVal);
|
||||
return GetPointOnPlane(p0, p1, p2, p3);
|
||||
}
|
||||
|
||||
chose = UUtils::Random(0., 2.2);
|
||||
if ((chose >= 0.) && (chose < 1.))
|
||||
{
|
||||
rang = fStartPhi;
|
||||
}
|
||||
else
|
||||
{
|
||||
rang = fEndPhi;
|
||||
}
|
||||
|
||||
cosphi1 = std::cos(rang);
|
||||
rad1 = fOriginalParameters.Rmin[j];
|
||||
sinphi1 = std::sin(rang);
|
||||
rad2 = fOriginalParameters.Rmax[j];
|
||||
|
||||
p0 = UVector3(rad1 * cosphi1, rad1 * sinphi1,
|
||||
fOriginalParameters.fZValues[j]);
|
||||
p1 = UVector3(rad2 * cosphi1, rad2 * sinphi1,
|
||||
fOriginalParameters.fZValues[j]);
|
||||
|
||||
rad1 = fOriginalParameters.Rmax[j + 1];
|
||||
rad2 = fOriginalParameters.Rmin[j + 1];
|
||||
|
||||
p2 = UVector3(rad1 * cosphi1, rad1 * sinphi1,
|
||||
fOriginalParameters.fZValues[j + 1]);
|
||||
p3 = UVector3(rad2 * cosphi1, rad2 * sinphi1,
|
||||
fOriginalParameters.fZValues[j + 1]);
|
||||
return GetPointOnPlane(p0, p1, p2, p3);
|
||||
}
|
||||
else // Generic polyhedra
|
||||
{
|
||||
return GetPointOnSurfaceGeneric();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// UPolyhedraHistorical stuff
|
||||
//
|
||||
UPolyhedraHistorical::UPolyhedraHistorical()
|
||||
: fStartAngle(0.), fOpeningAngle(0.), fNumSide(0), fNumZPlanes(0),
|
||||
fZValues(0), Rmin(0), Rmax(0)
|
||||
{
|
||||
}
|
||||
|
||||
UPolyhedraHistorical::~UPolyhedraHistorical()
|
||||
{
|
||||
}
|
||||
|
||||
UPolyhedraHistorical::
|
||||
UPolyhedraHistorical(const UPolyhedraHistorical& source)
|
||||
{
|
||||
fStartAngle = source.fStartAngle;
|
||||
fOpeningAngle = source.fOpeningAngle;
|
||||
fNumSide = source.fNumSide;
|
||||
fNumZPlanes = source.fNumZPlanes;
|
||||
|
||||
fZValues = source.fZValues;
|
||||
Rmin = source.Rmin;
|
||||
Rmax = source.Rmax;
|
||||
}
|
||||
|
||||
UPolyhedraHistorical&
|
||||
UPolyhedraHistorical::operator=(const UPolyhedraHistorical& right)
|
||||
{
|
||||
if (&right == this) return *this;
|
||||
|
||||
fStartAngle = right.fStartAngle;
|
||||
fOpeningAngle = right.fOpeningAngle;
|
||||
fNumSide = right.fNumSide;
|
||||
fNumZPlanes = right.fNumZPlanes;
|
||||
|
||||
fZValues = right.fZValues;
|
||||
Rmin = right.Rmin;
|
||||
Rmax = right.Rmax;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void UPolyhedra::Extent(UVector3& aMin, UVector3& aMax) const
|
||||
{
|
||||
fEnclosingCylinder->Extent(aMin, aMax);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// DistanceToIn
|
||||
//
|
||||
// This is an override of G4VCSGfaceted::Inside, created in order
|
||||
// to speed things up by first checking with G4EnclosingCylinder.
|
||||
//
|
||||
double UPolyhedra::DistanceToIn(const UVector3& p,
|
||||
const UVector3& v, double aPstep) const
|
||||
{
|
||||
//
|
||||
// Quick test
|
||||
//
|
||||
if (fNoVoxels && fEnclosingCylinder->ShouldMiss(p, v))
|
||||
return UUtils::kInfinity;
|
||||
|
||||
//
|
||||
// Long answer
|
||||
//
|
||||
return UVCSGfaceted::DistanceToIn(p, v, aPstep);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,597 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UReduciblePolygon
|
||||
//
|
||||
// 19.09.13 Marek Gayer
|
||||
// Created from original implementation in Geant4
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#include "UUtils.hh"
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
#include "UReduciblePolygon.hh"
|
||||
|
||||
//
|
||||
// Constructor: with simple arrays
|
||||
//
|
||||
UReduciblePolygon::UReduciblePolygon(const double a[],
|
||||
const double b[],
|
||||
int n)
|
||||
: aMin(0.), aMax(0.), bMin(0.), bMax(0.),
|
||||
vertexHead(0)
|
||||
{
|
||||
//
|
||||
// Do all of the real work in Create
|
||||
//
|
||||
Create(a, b, n);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Constructor: special PGON/PCON case
|
||||
//
|
||||
UReduciblePolygon::UReduciblePolygon(const double rmin[],
|
||||
const double rmax[],
|
||||
const double z[], int n)
|
||||
: aMin(0.), aMax(0.), bMin(0.), bMax(0.),
|
||||
vertexHead(0)
|
||||
{
|
||||
//
|
||||
// Translate
|
||||
//
|
||||
double* a = new double[n * 2];
|
||||
double* b = new double[n * 2];
|
||||
|
||||
double* rOut = a + n,
|
||||
*zOut = b + n,
|
||||
*rIn = rOut - 1,
|
||||
*zIn = zOut - 1;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < n; i++, rOut++, zOut++, rIn--, zIn--)
|
||||
{
|
||||
*rOut = rmax[i];
|
||||
*rIn = rmin[i];
|
||||
*zOut = *zIn = z[i];
|
||||
}
|
||||
|
||||
Create(a, b, n * 2);
|
||||
|
||||
delete [] a;
|
||||
delete [] b;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Create
|
||||
//
|
||||
// To be called by constructors, fill in the list and statistics for a new
|
||||
// polygon
|
||||
//
|
||||
void UReduciblePolygon::Create(const double a[],
|
||||
const double b[], int n)
|
||||
{
|
||||
if (n < 3)
|
||||
UUtils::Exception("UReduciblePolygon::Create()", "GeomSolids0002",
|
||||
FatalErrorInArguments, 1, "Less than 3 vertices specified.");
|
||||
|
||||
const double* anext = a, *bnext = b;
|
||||
|
||||
ABVertex* prev = 0;
|
||||
do
|
||||
{
|
||||
ABVertex* newVertex = new ABVertex;
|
||||
newVertex->a = *anext;
|
||||
newVertex->b = *bnext;
|
||||
newVertex->next = 0;
|
||||
if (prev == 0)
|
||||
{
|
||||
vertexHead = newVertex;
|
||||
}
|
||||
else
|
||||
{
|
||||
prev->next = newVertex;
|
||||
}
|
||||
|
||||
prev = newVertex;
|
||||
}
|
||||
while (++anext, ++bnext < b + n);
|
||||
|
||||
numVertices = n;
|
||||
|
||||
CalculateMaxMin();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Destructor
|
||||
//
|
||||
UReduciblePolygon::~UReduciblePolygon()
|
||||
{
|
||||
ABVertex* curr = vertexHead;
|
||||
while (curr)
|
||||
{
|
||||
ABVertex* toDelete = curr;
|
||||
curr = curr->next;
|
||||
delete toDelete;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// CopyVertices
|
||||
//
|
||||
// Copy contents into simple linear arrays.
|
||||
// ***** CAUTION ***** Be care to declare the arrays to a large
|
||||
// enough size!
|
||||
//
|
||||
void UReduciblePolygon::CopyVertices(double a[], double b[]) const
|
||||
{
|
||||
double* anext = a, *bnext = b;
|
||||
ABVertex* curr = vertexHead;
|
||||
while (curr)
|
||||
{
|
||||
*anext++ = curr->a;
|
||||
*bnext++ = curr->b;
|
||||
curr = curr->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// ScaleA
|
||||
//
|
||||
// Multiply all a values by a common scale
|
||||
//
|
||||
void UReduciblePolygon::ScaleA(double scale)
|
||||
{
|
||||
ABVertex* curr = vertexHead;
|
||||
while (curr)
|
||||
{
|
||||
curr->a *= scale;
|
||||
curr = curr->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// ScaleB
|
||||
//
|
||||
// Multiply all b values by a common scale
|
||||
//
|
||||
void UReduciblePolygon::ScaleB(double scale)
|
||||
{
|
||||
ABVertex* curr = vertexHead;
|
||||
while (curr)
|
||||
{
|
||||
curr->b *= scale;
|
||||
curr = curr->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// RemoveDuplicateVertices
|
||||
//
|
||||
// Remove adjacent vertices that are equal. Returns "false" if there
|
||||
// is a problem (too few vertices remaining).
|
||||
//
|
||||
bool UReduciblePolygon::RemoveDuplicateVertices(double tolerance)
|
||||
{
|
||||
ABVertex* curr = vertexHead,
|
||||
*prev = 0, *next = 0;
|
||||
while (curr)
|
||||
{
|
||||
next = curr->next;
|
||||
if (next == 0) next = vertexHead;
|
||||
|
||||
if (std::fabs(curr->a - next->a) < tolerance &&
|
||||
std::fabs(curr->b - next->b) < tolerance)
|
||||
{
|
||||
//
|
||||
// Duplicate found: do we have > 3 vertices?
|
||||
//
|
||||
if (numVertices <= 3)
|
||||
{
|
||||
CalculateMaxMin();
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Delete
|
||||
//
|
||||
ABVertex* toDelete = curr;
|
||||
curr = curr->next;
|
||||
delete toDelete;
|
||||
|
||||
numVertices--;
|
||||
|
||||
if (prev) prev->next = curr;
|
||||
else vertexHead = curr;
|
||||
}
|
||||
else
|
||||
{
|
||||
prev = curr;
|
||||
curr = curr->next;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// In principle, this is not needed, but why not just play it safe?
|
||||
//
|
||||
CalculateMaxMin();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// RemoveRedundantVertices
|
||||
//
|
||||
// Remove any unneeded vertices, i.e. those vertices which
|
||||
// are on the line connecting the previous and next vertices.
|
||||
//
|
||||
bool UReduciblePolygon::RemoveRedundantVertices(double tolerance)
|
||||
{
|
||||
//
|
||||
// Under these circumstances, we can quit now!
|
||||
//
|
||||
if (numVertices <= 2) return false;
|
||||
|
||||
double tolerance2 = tolerance * tolerance;
|
||||
|
||||
//
|
||||
// Loop over all vertices
|
||||
//
|
||||
ABVertex* curr = vertexHead, *next = 0;
|
||||
while (curr)
|
||||
{
|
||||
next = curr->next;
|
||||
if (next == 0) next = vertexHead;
|
||||
|
||||
double da = next->a - curr->a,
|
||||
db = next->b - curr->b;
|
||||
|
||||
//
|
||||
// Loop over all subsequent vertices, up to curr
|
||||
//
|
||||
for (;;)
|
||||
{
|
||||
//
|
||||
// Get vertex after next
|
||||
//
|
||||
ABVertex* test = next->next;
|
||||
if (test == 0) test = vertexHead;
|
||||
|
||||
//
|
||||
// If we are back to the original vertex, stop
|
||||
//
|
||||
if (test == curr) break;
|
||||
|
||||
//
|
||||
// Test for parallel line segments
|
||||
//
|
||||
double dat = test->a - curr->a,
|
||||
dbt = test->b - curr->b;
|
||||
|
||||
if (std::fabs(dat * db - dbt * da) > tolerance2) break;
|
||||
|
||||
//
|
||||
// Redundant vertex found: do we have > 3 vertices?
|
||||
//
|
||||
if (numVertices <= 3)
|
||||
{
|
||||
CalculateMaxMin();
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Delete vertex pointed to by next. Carefully!
|
||||
//
|
||||
if (curr->next)
|
||||
{
|
||||
// next is not head
|
||||
if (next->next)
|
||||
curr->next = test; // next is not tail
|
||||
else
|
||||
curr->next = 0; // New tail
|
||||
}
|
||||
else
|
||||
vertexHead = test; // New head
|
||||
|
||||
if ((curr != next) && (next != test)) delete next;
|
||||
|
||||
numVertices--;
|
||||
|
||||
//
|
||||
// Replace next by the vertex we just tested,
|
||||
// and keep on going...
|
||||
//
|
||||
next = test;
|
||||
da = dat;
|
||||
db = dbt;
|
||||
}
|
||||
curr = curr->next;
|
||||
}
|
||||
|
||||
//
|
||||
// In principle, this is not needed, but why not just play it safe?
|
||||
//
|
||||
CalculateMaxMin();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// ReverseOrder
|
||||
//
|
||||
// Reverse the order of the vertices
|
||||
//
|
||||
void UReduciblePolygon::ReverseOrder()
|
||||
{
|
||||
//
|
||||
// Loop over all vertices
|
||||
//
|
||||
ABVertex* prev = vertexHead;
|
||||
if (prev == 0) return; // No vertices
|
||||
|
||||
ABVertex* curr = prev->next;
|
||||
if (curr == 0) return; // Just one vertex
|
||||
|
||||
//
|
||||
// Our new tail
|
||||
//
|
||||
vertexHead->next = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
//
|
||||
// Save pointer to next vertex (in original order)
|
||||
//
|
||||
ABVertex* save = curr->next;
|
||||
|
||||
//
|
||||
// Replace it with a pointer to the previous one
|
||||
// (in original order)
|
||||
//
|
||||
curr->next = prev;
|
||||
|
||||
//
|
||||
// Last vertex?
|
||||
//
|
||||
if (save == 0) break;
|
||||
|
||||
//
|
||||
// Next vertex
|
||||
//
|
||||
prev = curr;
|
||||
curr = save;
|
||||
}
|
||||
|
||||
//
|
||||
// Our new head
|
||||
//
|
||||
vertexHead = curr;
|
||||
}
|
||||
|
||||
// StartWithZMin
|
||||
//
|
||||
// Starting alway with Zmin=bMin
|
||||
// This method is used for GenericPolycone
|
||||
//
|
||||
void UReduciblePolygon::StartWithZMin()
|
||||
{
|
||||
ABVertex* curr = vertexHead;
|
||||
double bcurr = curr->b;
|
||||
ABVertex* prev = curr;
|
||||
while (curr)
|
||||
{
|
||||
if (curr->b < bcurr)
|
||||
{
|
||||
bcurr = curr->b;
|
||||
ABVertex* curr1 = curr;
|
||||
while (curr1)
|
||||
{
|
||||
if (curr1->next == 0)
|
||||
{
|
||||
curr1->next = vertexHead;
|
||||
break;
|
||||
}
|
||||
curr1 = curr1->next;
|
||||
}
|
||||
vertexHead = curr;
|
||||
prev->next = 0;
|
||||
}
|
||||
prev = curr;
|
||||
curr = curr->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// CrossesItself
|
||||
//
|
||||
// Return "true" if the polygon crosses itself
|
||||
//
|
||||
// Warning: this routine is not very fast (runs as N**2)
|
||||
//
|
||||
bool UReduciblePolygon::CrossesItself(double tolerance)
|
||||
{
|
||||
double tolerance2 = tolerance * tolerance;
|
||||
double one = 1.0 - tolerance,
|
||||
zero = tolerance;
|
||||
//
|
||||
// Top loop over line segments. By the time we finish
|
||||
// with the second to last segment, we're done.
|
||||
//
|
||||
ABVertex* curr1 = vertexHead, *next1 = 0;
|
||||
while (curr1->next)
|
||||
{
|
||||
next1 = curr1->next;
|
||||
double da1 = next1->a - curr1->a,
|
||||
db1 = next1->b - curr1->b;
|
||||
|
||||
//
|
||||
// Inner loop over subsequent line segments
|
||||
//
|
||||
ABVertex* curr2 = next1->next;
|
||||
while (curr2)
|
||||
{
|
||||
ABVertex* next2 = curr2->next;
|
||||
if (next2 == 0) next2 = vertexHead;
|
||||
double da2 = next2->a - curr2->a,
|
||||
db2 = next2->b - curr2->b;
|
||||
double a12 = curr2->a - curr1->a,
|
||||
b12 = curr2->b - curr1->b;
|
||||
|
||||
//
|
||||
// Calculate intersection of the two lines
|
||||
//
|
||||
double deter = da1 * db2 - db1 * da2;
|
||||
if (std::fabs(deter) > tolerance2)
|
||||
{
|
||||
double s1, s2;
|
||||
s1 = (a12 * db2 - b12 * da2) / deter;
|
||||
|
||||
if (s1 >= zero && s1 < one)
|
||||
{
|
||||
s2 = -(da1 * b12 - db1 * a12) / deter;
|
||||
if (s2 >= zero && s2 < one) return true;
|
||||
}
|
||||
}
|
||||
curr2 = curr2->next;
|
||||
}
|
||||
curr1 = next1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// BisectedBy
|
||||
//
|
||||
// Decide if a line through two points crosses the polygon, within tolerance
|
||||
//
|
||||
bool UReduciblePolygon::BisectedBy(double a1, double b1,
|
||||
double a2, double b2,
|
||||
double tolerance)
|
||||
{
|
||||
int nNeg = 0, nPos = 0;
|
||||
|
||||
double a12 = a2 - a1, b12 = b2 - b1;
|
||||
double len12 = std::sqrt(a12 * a12 + b12 * b12);
|
||||
a12 /= len12;
|
||||
b12 /= len12;
|
||||
|
||||
ABVertex* curr = vertexHead;
|
||||
do
|
||||
{
|
||||
double av = curr->a - a1,
|
||||
bv = curr->b - b1;
|
||||
|
||||
double Cross = av * b12 - bv * a12;
|
||||
|
||||
if (Cross < -tolerance)
|
||||
{
|
||||
if (nPos) return true;
|
||||
nNeg++;
|
||||
}
|
||||
else if (Cross > tolerance)
|
||||
{
|
||||
if (nNeg) return true;
|
||||
nPos++;
|
||||
}
|
||||
curr = curr->next;
|
||||
}
|
||||
while (curr);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Area
|
||||
//
|
||||
// Calculated signed polygon area, where polygons specified in a
|
||||
// clockwise manner (where x==a, y==b) have negative area
|
||||
//
|
||||
// References: [O' Rourke (C)] pp. 18-27; [Gems II] pp. 5-6:
|
||||
// "The Area of a Simple Polygon", Jon Rokne.
|
||||
//
|
||||
double UReduciblePolygon::Area()
|
||||
{
|
||||
double answer = 0;
|
||||
|
||||
ABVertex* curr = vertexHead, *next;
|
||||
do
|
||||
{
|
||||
next = curr->next;
|
||||
if (next == 0) next = vertexHead;
|
||||
|
||||
answer += curr->a * next->b - curr->b * next->a;
|
||||
curr = curr->next;
|
||||
}
|
||||
while (curr);
|
||||
|
||||
return 0.5 * answer;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Print
|
||||
//
|
||||
void UReduciblePolygon::Print()
|
||||
{
|
||||
ABVertex* curr = vertexHead;
|
||||
do
|
||||
{
|
||||
std::cerr << curr->a << " " << curr->b << std::endl;
|
||||
curr = curr->next;
|
||||
}
|
||||
while (curr);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// CalculateMaxMin
|
||||
//
|
||||
// To be called when the vertices are changed, this
|
||||
// routine re-calculates global values
|
||||
//
|
||||
void UReduciblePolygon::CalculateMaxMin()
|
||||
{
|
||||
ABVertex* curr = vertexHead;
|
||||
aMin = aMax = curr->a;
|
||||
bMin = bMax = curr->b;
|
||||
curr = curr->next;
|
||||
while (curr)
|
||||
{
|
||||
if (curr->a < aMin)
|
||||
aMin = curr->a;
|
||||
else if (curr->a > aMax)
|
||||
aMax = curr->a;
|
||||
|
||||
if (curr->b < bMin)
|
||||
bMin = curr->b;
|
||||
else if (curr->b > bMax)
|
||||
bMax = curr->b;
|
||||
|
||||
curr = curr->next;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,655 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UTet
|
||||
//
|
||||
// 19.07.13 Tatiana Nikitina
|
||||
// Created from original implementation in Geant4
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include "UTet.hh"
|
||||
#include "UUtils.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Constructor - create a tetrahedron
|
||||
// This class is implemented separately from general polyhedra,
|
||||
// because the simplex geometry can be computed very quickly,
|
||||
// which may become important in situations imported from mesh generators,
|
||||
// in which a very large number of G4Tets are created.
|
||||
// A Tet has all of its geometrical information precomputed
|
||||
|
||||
UTet::UTet(const std::string& name,
|
||||
UVector3 anchor,
|
||||
UVector3 p2,
|
||||
UVector3 p3,
|
||||
UVector3 p4, bool* degeneracyFlag)
|
||||
: VUSolid(name), warningFlag(0)
|
||||
{
|
||||
// fV<x><y> is vector from vertex <y> to vertex <x>
|
||||
//
|
||||
UVector3 fV21 = p2 - anchor;
|
||||
UVector3 fV31 = p3 - anchor;
|
||||
UVector3 fV41 = p4 - anchor;
|
||||
|
||||
// make sure this is a correctly oriented set of points for the tetrahedron
|
||||
//
|
||||
double signed_vol = fV21.Cross(fV31).Dot(fV41);
|
||||
if (signed_vol < 0.0)
|
||||
{
|
||||
UVector3 temp(p4);
|
||||
p4 = p3;
|
||||
p3 = temp;
|
||||
temp = fV41;
|
||||
fV41 = fV31;
|
||||
fV31 = temp;
|
||||
}
|
||||
fCubicVolume = std::fabs(signed_vol) / 6.;
|
||||
|
||||
//UVector3 fV24=p2-p4;
|
||||
UVector3 fV43 = p4 - p3;
|
||||
UVector3 fV32 = p3 - p2;
|
||||
|
||||
fXMin = std::min(std::min(std::min(anchor.x, p2.x), p3.x), p4.x);
|
||||
fXMax = std::max(std::max(std::max(anchor.x, p2.x), p3.x), p4.x);
|
||||
fYMin = std::min(std::min(std::min(anchor.y, p2.y), p3.y), p4.y);
|
||||
fYMax = std::max(std::max(std::max(anchor.y, p2.y), p3.y), p4.y);
|
||||
fZMin = std::min(std::min(std::min(anchor.z, p2.z), p3.z), p4.z);
|
||||
fZMax = std::max(std::max(std::max(anchor.z, p2.z), p3.z), p4.z);
|
||||
|
||||
fDx = (fXMax - fXMin) * 0.5;
|
||||
fDy = (fYMax - fYMin) * 0.5;
|
||||
fDz = (fZMax - fZMin) * 0.5;
|
||||
|
||||
fMiddle = UVector3(fXMax + fXMin, fYMax + fYMin, fZMax + fZMin) * 0.5;
|
||||
fMaxSize = std::max(std::max(std::max((anchor - fMiddle).Mag(),
|
||||
(p2 - fMiddle).Mag()),
|
||||
(p3 - fMiddle).Mag()),
|
||||
(p4 - fMiddle).Mag());
|
||||
|
||||
bool degenerate = std::fabs(signed_vol) < 1e-9 * fMaxSize * fMaxSize * fMaxSize;
|
||||
|
||||
if (degeneracyFlag) *degeneracyFlag = degenerate;
|
||||
else if (degenerate)
|
||||
{
|
||||
UUtils::Exception("UTet::UTet()", "GeomSolids0002", FatalErrorInArguments, 1,
|
||||
"Degenerate tetrahedron not allowed.");
|
||||
}
|
||||
|
||||
fTol = 1e-9 * (std::fabs(fXMin) + std::fabs(fXMax) + std::fabs(fYMin)
|
||||
+ std::fabs(fYMax) + std::fabs(fZMin) + std::fabs(fZMax));
|
||||
//fTol=kCarTolerance;
|
||||
|
||||
fAnchor = anchor;
|
||||
fP2 = p2;
|
||||
fP3 = p3;
|
||||
fP4 = p4;
|
||||
|
||||
UVector3 fCenter123 = (anchor + p2 + p3) * (1.0 / 3.0); // face center
|
||||
UVector3 fCenter134 = (anchor + p4 + p3) * (1.0 / 3.0);
|
||||
UVector3 fCenter142 = (anchor + p4 + p2) * (1.0 / 3.0);
|
||||
UVector3 fCenter234 = (p2 + p3 + p4) * (1.0 / 3.0);
|
||||
|
||||
// compute area of each triangular face by cross product
|
||||
// and sum for total surface area
|
||||
|
||||
UVector3 normal123 = fV31.Cross(fV21);
|
||||
UVector3 normal134 = fV41.Cross(fV31);
|
||||
UVector3 normal142 = fV21.Cross(fV41);
|
||||
UVector3 normal234 = fV32.Cross(fV43);
|
||||
|
||||
fSurfaceArea = (
|
||||
normal123.Mag() +
|
||||
normal134.Mag() +
|
||||
normal142.Mag() +
|
||||
normal234.Mag()
|
||||
) / 2.0;
|
||||
|
||||
fNormal123 = normal123.Unit();
|
||||
fNormal134 = normal134.Unit();
|
||||
fNormal142 = normal142.Unit();
|
||||
fNormal234 = normal234.Unit();
|
||||
|
||||
fCdotN123 = fCenter123.Dot(fNormal123);
|
||||
fCdotN134 = fCenter134.Dot(fNormal134);
|
||||
fCdotN142 = fCenter142.Dot(fNormal142);
|
||||
fCdotN234 = fCenter234.Dot(fNormal234);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Destructor
|
||||
|
||||
UTet::~UTet()
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copy constructor
|
||||
|
||||
UTet::UTet(const UTet& rhs)
|
||||
: VUSolid(rhs),
|
||||
fCubicVolume(rhs.fCubicVolume), fSurfaceArea(rhs.fSurfaceArea),
|
||||
fAnchor(rhs.fAnchor),
|
||||
fP2(rhs.fP2), fP3(rhs.fP3), fP4(rhs.fP4), fMiddle(rhs.fMiddle),
|
||||
fNormal123(rhs.fNormal123), fNormal142(rhs.fNormal142),
|
||||
fNormal134(rhs.fNormal134), fNormal234(rhs.fNormal234),
|
||||
warningFlag(rhs.warningFlag), fCdotN123(rhs.fCdotN123),
|
||||
fCdotN142(rhs.fCdotN142), fCdotN134(rhs.fCdotN134),
|
||||
fCdotN234(rhs.fCdotN234), fXMin(rhs.fXMin), fXMax(rhs.fXMax),
|
||||
fYMin(rhs.fYMin), fYMax(rhs.fYMax), fZMin(rhs.fZMin), fZMax(rhs.fZMax),
|
||||
fDx(rhs.fDx), fDy(rhs.fDy), fDz(rhs.fDz), fTol(rhs.fTol),
|
||||
fMaxSize(rhs.fMaxSize)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Assignment operator
|
||||
|
||||
UTet& UTet::operator = (const UTet& rhs)
|
||||
{
|
||||
// Check assignment to self
|
||||
//
|
||||
if (this == &rhs)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Copy base class data
|
||||
//
|
||||
VUSolid::operator=(rhs);
|
||||
|
||||
// Copy data
|
||||
//
|
||||
fCubicVolume = rhs.fCubicVolume;
|
||||
fSurfaceArea = rhs.fSurfaceArea;
|
||||
fAnchor = rhs.fAnchor;
|
||||
fP2 = rhs.fP2;
|
||||
fP3 = rhs.fP3;
|
||||
fP4 = rhs.fP4;
|
||||
fMiddle = rhs.fMiddle;
|
||||
fNormal123 = rhs.fNormal123;
|
||||
fNormal142 = rhs.fNormal142;
|
||||
fNormal134 = rhs.fNormal134;
|
||||
fNormal234 = rhs.fNormal234;
|
||||
warningFlag = rhs.warningFlag;
|
||||
fCdotN123 = rhs.fCdotN123;
|
||||
fCdotN142 = rhs.fCdotN142;
|
||||
fCdotN134 = rhs.fCdotN134;
|
||||
fCdotN234 = rhs.fCdotN234;
|
||||
fXMin = rhs.fXMin;
|
||||
fXMax = rhs.fXMax;
|
||||
fYMin = rhs.fYMin;
|
||||
fYMax = rhs.fYMax;
|
||||
fZMin = rhs.fZMin;
|
||||
fZMax = rhs.fZMax;
|
||||
fDx = rhs.fDx;
|
||||
fDy = rhs.fDy;
|
||||
fDz = rhs.fDz;
|
||||
fTol = rhs.fTol;
|
||||
fMaxSize = rhs.fMaxSize;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Return whether point inside/outside/on surface, using tolerance
|
||||
|
||||
VUSolid::EnumInside UTet::Inside(const UVector3& p) const
|
||||
{
|
||||
double r123, r134, r142, r234;
|
||||
|
||||
// this is written to allow if-statement truncation so the outside test
|
||||
// (where most of the world is) can fail very quickly and efficiently
|
||||
|
||||
if ((r123 = p.Dot(fNormal123) - fCdotN123) > fTol ||
|
||||
(r134 = p.Dot(fNormal134) - fCdotN134) > fTol ||
|
||||
(r142 = p.Dot(fNormal142) - fCdotN142) > fTol ||
|
||||
(r234 = p.Dot(fNormal234) - fCdotN234) > fTol)
|
||||
{
|
||||
return eOutside; // at least one is out!
|
||||
}
|
||||
else if ((r123 < -fTol) && (r134 < -fTol) && (r142 < -fTol) && (r234 < -fTol))
|
||||
{
|
||||
return eInside; // all are definitively inside
|
||||
}
|
||||
else
|
||||
{
|
||||
return eSurface; // too close to tell
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Calculate side nearest to p, and return normal
|
||||
// If two sides are equidistant, normal of first side (x/y/z)
|
||||
// encountered returned.
|
||||
// This assumes that we are looking from the inside!
|
||||
bool UTet::Normal(const UVector3& p, UVector3& n) const
|
||||
{
|
||||
double r123 = std::fabs(p.Dot(fNormal123) - fCdotN123);
|
||||
double r134 = std::fabs(p.Dot(fNormal134) - fCdotN134);
|
||||
double r142 = std::fabs(p.Dot(fNormal142) - fCdotN142);
|
||||
double r234 = std::fabs(p.Dot(fNormal234) - fCdotN234);
|
||||
|
||||
static const double delta = 0.5 * fTol;
|
||||
UVector3 sumnorm(0., 0., 0.);
|
||||
int noSurfaces = 0;
|
||||
|
||||
if (r123 <= delta)
|
||||
{
|
||||
noSurfaces ++;
|
||||
sumnorm = fNormal123;
|
||||
}
|
||||
|
||||
if (r134 <= delta)
|
||||
{
|
||||
noSurfaces ++;
|
||||
sumnorm += fNormal134;
|
||||
}
|
||||
|
||||
if (r142 <= delta)
|
||||
{
|
||||
noSurfaces ++;
|
||||
sumnorm += fNormal142;
|
||||
}
|
||||
if (r234 <= delta)
|
||||
{
|
||||
noSurfaces ++;
|
||||
sumnorm += fNormal234;
|
||||
}
|
||||
|
||||
if (noSurfaces > 0)
|
||||
{
|
||||
if (noSurfaces == 1)
|
||||
{
|
||||
n = sumnorm;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
n = sumnorm.Unit();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else // Approximative Surface Normal
|
||||
{
|
||||
|
||||
if ((r123 <= r134) && (r123 <= r142) && (r123 <= r234))
|
||||
{
|
||||
n = fNormal123;
|
||||
}
|
||||
else if ((r134 <= r142) && (r134 <= r234))
|
||||
{
|
||||
n = fNormal134;
|
||||
}
|
||||
else if (r142 <= r234)
|
||||
{
|
||||
n = fNormal142;
|
||||
}
|
||||
n = fNormal234;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Calculate distance to box from an outside point
|
||||
// - return kInfinity if no intersection.
|
||||
// All this is very unrolled, for speed.
|
||||
|
||||
double UTet::DistanceToIn(const UVector3& p,
|
||||
const UVector3& v, double /*aPstep*/) const
|
||||
{
|
||||
UVector3 vu(v.Unit()), hp;
|
||||
double vdotn, t, tmin = UUtils::kInfinity;
|
||||
|
||||
double extraDistance = 10.0 * fTol; // a little ways into the solid
|
||||
|
||||
vdotn = -vu.Dot(fNormal123);
|
||||
if (vdotn > 1e-12)
|
||||
{
|
||||
// this is a candidate face, since it is pointing at us
|
||||
t = (p.Dot(fNormal123) - fCdotN123) / vdotn; // # distance to intersection
|
||||
if ((t >= -fTol) && (t < tmin))
|
||||
{
|
||||
// if not true, we're going away from this face or it's not close
|
||||
hp = p + vu * (t + extraDistance); // a little beyond point of intersection
|
||||
if ((hp.Dot(fNormal134) - fCdotN134 < 0.0) &&
|
||||
(hp.Dot(fNormal142) - fCdotN142 < 0.0) &&
|
||||
(hp.Dot(fNormal234) - fCdotN234 < 0.0))
|
||||
{
|
||||
tmin = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vdotn = -vu.Dot(fNormal134);
|
||||
if (vdotn > 1e-12)
|
||||
{
|
||||
// # this is a candidate face, since it is pointing at us
|
||||
t = (p.Dot(fNormal134) - fCdotN134) / vdotn; // # distance to intersection
|
||||
if ((t >= -fTol) && (t < tmin))
|
||||
{
|
||||
// if not true, we're going away from this face
|
||||
hp = p + vu * (t + extraDistance); // a little beyond point of intersection
|
||||
if ((hp.Dot(fNormal123) - fCdotN123 < 0.0) &&
|
||||
(hp.Dot(fNormal142) - fCdotN142 < 0.0) &&
|
||||
(hp.Dot(fNormal234) - fCdotN234 < 0.0))
|
||||
{
|
||||
tmin = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vdotn = -vu.Dot(fNormal142);
|
||||
if (vdotn > 1e-12)
|
||||
{
|
||||
// # this is a candidate face, since it is pointing at us
|
||||
t = (p.Dot(fNormal142) - fCdotN142) / vdotn; // # distance to intersection
|
||||
if ((t >= -fTol) && (t < tmin))
|
||||
{
|
||||
// if not true, we're going away from this face
|
||||
hp = p + vu * (t + extraDistance); // a little beyond point of intersection
|
||||
if ((hp.Dot(fNormal123) - fCdotN123 < 0.0) &&
|
||||
(hp.Dot(fNormal134) - fCdotN134 < 0.0) &&
|
||||
(hp.Dot(fNormal234) - fCdotN234 < 0.0))
|
||||
{
|
||||
tmin = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vdotn = -vu.Dot(fNormal234);
|
||||
if (vdotn > 1e-12)
|
||||
{
|
||||
// # this is a candidate face, since it is pointing at us
|
||||
t = (p.Dot(fNormal234) - fCdotN234) / vdotn; // # distance to intersection
|
||||
if ((t >= -fTol) && (t < tmin))
|
||||
{
|
||||
// if not true, we're going away from this face
|
||||
hp = p + vu * (t + extraDistance); // a little beyond point of intersection
|
||||
if ((hp.Dot(fNormal123) - fCdotN123 < 0.0) &&
|
||||
(hp.Dot(fNormal134) - fCdotN134 < 0.0) &&
|
||||
(hp.Dot(fNormal142) - fCdotN142 < 0.0))
|
||||
{
|
||||
tmin = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return std::max(0.0, tmin);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Approximate distance to tet.
|
||||
// returns distance to sphere centered on bounding box
|
||||
// - If inside return 0
|
||||
double UTet::SafetyFromOutside(const UVector3& p, bool /*aAccurate*/) const
|
||||
|
||||
{
|
||||
double dd = (p - fMiddle).Mag() - fMaxSize - fTol;
|
||||
return std::max(0.0, dd);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Calcluate distance to surface of box from inside
|
||||
// by calculating distances to box's x/y/z planes.
|
||||
// Smallest distance is exact distance to exiting.
|
||||
double UTet::DistanceToOut(const UVector3& p, const UVector3& v,
|
||||
UVector3& n, bool& convex, double /*aPstep*/) const
|
||||
{
|
||||
UVector3 vu(v.Unit());
|
||||
double t1 = UUtils::kInfinity, t2 = UUtils::kInfinity, t3 = UUtils::kInfinity, t4 = UUtils::kInfinity, vdotn, tt;
|
||||
|
||||
vdotn = vu.Dot(fNormal123);
|
||||
if (vdotn > 1e-12) // #we're heading towards this face, so it is a candidate
|
||||
{
|
||||
t1 = (fCdotN123 - p.Dot(fNormal123)) / vdotn; // # distance to intersection
|
||||
}
|
||||
|
||||
vdotn = vu.Dot(fNormal134);
|
||||
if (vdotn > 1e-12) // #we're heading towards this face, so it is a candidate
|
||||
{
|
||||
t2 = (fCdotN134 - p.Dot(fNormal134)) / vdotn; // # distance to intersection
|
||||
}
|
||||
|
||||
vdotn = vu.Dot(fNormal142);
|
||||
if (vdotn > 1e-12) // #we're heading towards this face, so it is a candidate
|
||||
{
|
||||
t3 = (fCdotN142 - p.Dot(fNormal142)) / vdotn; // # distance to intersection
|
||||
}
|
||||
|
||||
vdotn = vu.Dot(fNormal234);
|
||||
if (vdotn > 1e-12) // #we're heading towards this face, so it is a candidate
|
||||
{
|
||||
t4 = (fCdotN234 - p.Dot(fNormal234)) / vdotn; // # distance to intersection
|
||||
}
|
||||
|
||||
tt = std::min(std::min(std::min(t1, t2), t3), t4);
|
||||
|
||||
if (warningFlag && (tt == UUtils::kInfinity || tt < -fTol))
|
||||
{
|
||||
// DumpInfo();
|
||||
std::ostringstream message;
|
||||
message << "No good intersection found or already outside!?" << std::endl
|
||||
<< "p = " << p << std::endl
|
||||
<< "v = " << v << std::endl
|
||||
<< "t1, t2, t3, t4 "
|
||||
<< t1 << ", " << t2 << ", " << t3 << ", " << t4;
|
||||
|
||||
UUtils::Exception("UTet::DistanceToOut(p,v,...)", "GeomSolids1002",
|
||||
Warning, 1, message.str().c_str());
|
||||
if (convex)
|
||||
{
|
||||
convex = false; // flag normal as meaningless
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
static UVector3 normal;
|
||||
if (tt == t1)
|
||||
{
|
||||
normal = fNormal123;
|
||||
}
|
||||
else if (tt == t2)
|
||||
{
|
||||
normal = fNormal134;
|
||||
}
|
||||
else if (tt == t3)
|
||||
{
|
||||
normal = fNormal142;
|
||||
}
|
||||
else if (tt == t4)
|
||||
{
|
||||
normal = fNormal234;
|
||||
}
|
||||
n = normal;
|
||||
if (convex)
|
||||
{
|
||||
convex = true;
|
||||
}
|
||||
}
|
||||
|
||||
return std::max(tt, 0.0); // avoid tt<0.0 by a tiny bit
|
||||
// if we are right on a face
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Calculate exact shortest distance to any boundary from inside
|
||||
// - If outside return 0
|
||||
double UTet::SafetyFromInside(const UVector3& p, bool /*aAccurate*/) const
|
||||
{
|
||||
double t1, t2, t3, t4;
|
||||
t1 = fCdotN123 - p.Dot(fNormal123); // distance to plane, positive if inside
|
||||
t2 = fCdotN134 - p.Dot(fNormal134); // distance to plane
|
||||
t3 = fCdotN142 - p.Dot(fNormal142); // distance to plane
|
||||
t4 = fCdotN234 - p.Dot(fNormal234); // distance to plane
|
||||
|
||||
// if any one of these is negative, we are outside,
|
||||
// so return zero in that case
|
||||
|
||||
double tmin = std::min(std::min(std::min(t1, t2), t3), t4);
|
||||
return (tmin < fTol) ? 0 : tmin;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Stream object contents to an output stream
|
||||
|
||||
std::ostream& UTet::StreamInfo(std::ostream& os) const
|
||||
{
|
||||
int oldprc = os.precision(16);
|
||||
os << "-----------------------------------------------------------\n"
|
||||
<< " *** Dump for solid - " << GetName() << " ***\n"
|
||||
<< " ===================================================\n"
|
||||
<< " Solid type: UTet\n"
|
||||
<< " Parameters: \n"
|
||||
<< " anchor: " << fAnchor << " \n"
|
||||
<< " p2: " << fP2 << " \n"
|
||||
<< " p3: " << fP3 << " \n"
|
||||
<< " p4: " << fP4 << " \n"
|
||||
<< " normal123: " << fNormal123 << " \n"
|
||||
<< " normal134: " << fNormal134 << " \n"
|
||||
<< " normal142: " << fNormal142 << " \n"
|
||||
<< " normal234: " << fNormal234 << " \n"
|
||||
<< "-----------------------------------------------------------\n";
|
||||
os.precision(oldprc);
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// GetPointOnFace
|
||||
//
|
||||
// Auxiliary method for get point on surface
|
||||
|
||||
UVector3 UTet::GetPointOnFace(UVector3 p1, UVector3 p2,
|
||||
UVector3 p3, double& area) const
|
||||
{
|
||||
double lambda1, lambda2;
|
||||
UVector3 v, w;
|
||||
|
||||
v = p3 - p1;
|
||||
w = p1 - p2;
|
||||
|
||||
lambda1 = UUtils::Random(0., 1.);
|
||||
lambda2 = UUtils::Random(0., lambda1);
|
||||
|
||||
area = 0.5 * (v.Cross(w)).Mag();
|
||||
return (p2 + lambda1 * w + lambda2 * v);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// GetPointOnSurface
|
||||
|
||||
UVector3 UTet::GetPointOnSurface() const
|
||||
{
|
||||
double chose, aOne, aTwo, aThree, aFour;
|
||||
UVector3 p1, p2, p3, p4;
|
||||
|
||||
p1 = GetPointOnFace(fAnchor, fP2, fP3, aOne);
|
||||
p2 = GetPointOnFace(fAnchor, fP4, fP3, aTwo);
|
||||
p3 = GetPointOnFace(fAnchor, fP4, fP2, aThree);
|
||||
p4 = GetPointOnFace(fP4, fP3, fP2, aFour);
|
||||
|
||||
chose = UUtils::Random(0., aOne + aTwo + aThree + aFour);
|
||||
if ((chose >= 0.) && (chose < aOne))
|
||||
{
|
||||
return p1;
|
||||
}
|
||||
else if ((chose >= aOne) && (chose < aOne + aTwo))
|
||||
{
|
||||
return p2;
|
||||
}
|
||||
else if ((chose >= aOne + aTwo) && (chose < aOne + aTwo + aThree))
|
||||
{
|
||||
return p3;
|
||||
}
|
||||
return p4;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// GetVertices
|
||||
|
||||
std::vector<UVector3> UTet::GetVertices() const
|
||||
{
|
||||
std::vector<UVector3> vertices(4);
|
||||
vertices[0] = fAnchor;
|
||||
vertices[1] = fP2;
|
||||
vertices[2] = fP3;
|
||||
vertices[3] = fP4;
|
||||
|
||||
return vertices;
|
||||
}
|
||||
//______________________________________________________________________________
|
||||
void UTet::Extent(UVector3& aMin, UVector3& aMax) const
|
||||
{
|
||||
// Returns the full 3D cartesian extent of the solid.
|
||||
aMin.x = -fDx;
|
||||
aMax.x = fDx;
|
||||
aMin.y = -fDy;
|
||||
aMax.y = fDy;
|
||||
aMin.z = -fDz;
|
||||
aMax.z = fDz;
|
||||
}
|
||||
//______________________________________________________________________________
|
||||
void UTet::GetParametersList(int, double* aArray) const
|
||||
{
|
||||
aArray[0] = fAnchor.x;
|
||||
aArray[1] = fAnchor.y;
|
||||
aArray[2] = fAnchor.z;
|
||||
aArray[3] = fP2.x;
|
||||
aArray[4] = fP2.y;
|
||||
aArray[5] = fP2.z;
|
||||
aArray[6] = fP3.x;
|
||||
aArray[7] = fP3.y;
|
||||
aArray[8] = fP3.z;
|
||||
aArray[9] = fP4.x;
|
||||
aArray[10] = fP4.y;
|
||||
aArray[11] = fP4.z;
|
||||
}
|
||||
//______________________________________________________________________________
|
||||
UGeometryType UTet::GetEntityType() const
|
||||
{
|
||||
return "Tet";
|
||||
}
|
||||
//______________________________________________________________________________
|
||||
double UTet::Capacity()
|
||||
{
|
||||
return fCubicVolume;
|
||||
}
|
||||
//______________________________________________________________________________
|
||||
double UTet::SurfaceArea()
|
||||
{
|
||||
return fSurfaceArea;
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UTransform3D
|
||||
//
|
||||
// 19.09.12 Marek Gayer
|
||||
// Created from original implementation in CLHEP
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
||||
#include "UTransform3D.hh"
|
||||
#include "UUtils.hh"
|
||||
|
||||
const static double kIdRot[9] =
|
||||
{
|
||||
1.0, 0.0, 0.0,
|
||||
0.0, 1.0, 0.0,
|
||||
0.0, 0.0, 1.0
|
||||
};
|
||||
|
||||
//______________________________________________________________________________
|
||||
UTransform3D::UTransform3D()
|
||||
{
|
||||
// Dummy constructor
|
||||
fTr.Set(0);
|
||||
std::memcpy(fRot, kIdRot, sizeof(kIdRot));
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
UTransform3D::UTransform3D(double tx, double ty, double tz,
|
||||
double phi, double theta, double psi)
|
||||
{
|
||||
// Constructor providing a translation and Euler angles
|
||||
// See description for SetAngles() method.
|
||||
// This represent the composition of : first a rotation about Z axis with
|
||||
// angle phi, then a rotation with theta about the rotated X axis, and
|
||||
// finally a rotation with psi about the new Z axis.
|
||||
|
||||
fTr.Set(tx, ty, tz);
|
||||
SetAngles(phi, theta, psi);
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
UTransform3D::UTransform3D(const UTransform3D& other)
|
||||
{
|
||||
// Copy constructor.
|
||||
|
||||
fTr = other.fTr;
|
||||
std::memcpy(fRot, other.fRot, sizeof(kIdRot));
|
||||
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
UTransform3D& UTransform3D::operator = (const UTransform3D& other)
|
||||
{
|
||||
if (&other == this) return *this;
|
||||
fTr = other.fTr;
|
||||
std::memcpy(fRot, other.fRot, sizeof(kIdRot));
|
||||
return *this;
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
void UTransform3D::SetAngles(double phi, double theta, double psi)
|
||||
{
|
||||
// Set the rotation from Euler angles in the X-axis convention
|
||||
// See: http://mathworld.wolfram.com/EulerAngles.html
|
||||
// This represent the composition of : first a rotation about Z axis with
|
||||
// angle phi, then a rotation with theta about the rotated X axis, and
|
||||
// finally a rotation with psi about the new Z axis.
|
||||
|
||||
// NOTE: angles are in degrees
|
||||
double degrad = UUtils::kDegToRad;
|
||||
double sinphi = std::sin(degrad * phi);
|
||||
double cosphi = std::cos(degrad * phi);
|
||||
double sinthe = std::sin(degrad * theta);
|
||||
double costhe = std::cos(degrad * theta);
|
||||
double sinpsi = std::sin(degrad * psi);
|
||||
double cospsi = std::cos(degrad * psi);
|
||||
|
||||
fRot[0] = cospsi * cosphi - costhe * sinphi * sinpsi;
|
||||
fRot[1] = -sinpsi * cosphi - costhe * sinphi * cospsi;
|
||||
fRot[2] = sinthe * sinphi;
|
||||
fRot[3] = cospsi * sinphi + costhe * cosphi * sinpsi;
|
||||
fRot[4] = -sinpsi * sinphi + costhe * cosphi * cospsi;
|
||||
fRot[5] = -sinthe * cosphi;
|
||||
fRot[6] = sinpsi * sinthe;
|
||||
fRot[7] = cospsi * sinthe;
|
||||
fRot[8] = costhe;
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
void UTransform3D::RotateX(double angle)
|
||||
{
|
||||
// Rotate the transformation about the X axis with a given angle (in degrees).
|
||||
double phi = angle * UUtils::kDegToRad;
|
||||
double c = std::cos(phi);
|
||||
double s = std::sin(phi);
|
||||
double v[9];
|
||||
v[0] = fRot[0];
|
||||
v[1] = fRot[1];
|
||||
v[2] = fRot[2];
|
||||
v[3] = c * fRot[3] - s * fRot[6];
|
||||
v[4] = c * fRot[4] - s * fRot[7];
|
||||
v[5] = c * fRot[5] - s * fRot[8];
|
||||
v[6] = s * fRot[3] + c * fRot[6];
|
||||
v[7] = s * fRot[4] + c * fRot[7];
|
||||
v[8] = s * fRot[5] + c * fRot[8];
|
||||
std::memcpy(fRot, v, sizeof(kIdRot));
|
||||
|
||||
fTr.Set(fTr.x, c * fTr.y - s * fTr.z, s * fTr.y + c * fTr.z);
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
void UTransform3D::RotateY(double angle)
|
||||
{
|
||||
// Rotate the transformation about the Y axis with a given angle (in degrees).
|
||||
double phi = angle * UUtils::kDegToRad;
|
||||
double c = std::cos(phi);
|
||||
double s = std::sin(phi);
|
||||
double v[9];
|
||||
v[0] = c * fRot[0] + s * fRot[6];
|
||||
v[1] = c * fRot[1] + s * fRot[7];
|
||||
v[2] = c * fRot[2] + s * fRot[8];
|
||||
v[3] = fRot[3];
|
||||
v[4] = fRot[4];
|
||||
v[5] = fRot[5];
|
||||
v[6] = -s * fRot[0] + c * fRot[6];
|
||||
v[7] = -s * fRot[1] + c * fRot[7];
|
||||
v[8] = -s * fRot[2] + c * fRot[8];
|
||||
std::memcpy(fRot, v, sizeof(kIdRot));
|
||||
|
||||
fTr.Set(c * fTr.x + s * fTr.z, fTr.y, -s * fTr.x + c * fTr.z);
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
void UTransform3D::RotateZ(double angle)
|
||||
{
|
||||
// Rotate the transformation about the Z axis with a given angle (in degrees).
|
||||
double phi = angle * UUtils::kDegToRad;
|
||||
double c = std::cos(phi);
|
||||
double s = std::sin(phi);
|
||||
double v[9];
|
||||
v[0] = c * fRot[0] - s * fRot[3];
|
||||
v[1] = c * fRot[1] - s * fRot[4];
|
||||
v[2] = c * fRot[2] - s * fRot[5];
|
||||
v[3] = s * fRot[0] + c * fRot[3];
|
||||
v[4] = s * fRot[1] + c * fRot[4];
|
||||
v[5] = s * fRot[2] + c * fRot[5];
|
||||
v[6] = fRot[6];
|
||||
v[7] = fRot[7];
|
||||
v[8] = fRot[8];
|
||||
std::memcpy(&fRot[0], v, sizeof(kIdRot));
|
||||
|
||||
fTr.Set(c * fTr.x - s * fTr.y, s * fTr.x + c * fTr.y, fTr.z);
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
UVector3 UTransform3D::GlobalPoint(const UVector3& local) const
|
||||
{
|
||||
// Returns global point coordinates converted from the local frame defined
|
||||
// by the transformation. This is defined by multiplying this transformation
|
||||
// with the local vector.
|
||||
UVector3 global;
|
||||
global.x = fTr.x + local.x * fRot[0] + local.y * fRot[1] + local.z * fRot[2];
|
||||
global.y = fTr.y + local.x * fRot[3] + local.y * fRot[4] + local.z * fRot[5];
|
||||
global.z = fTr.z + local.x * fRot[6] + local.y * fRot[7] + local.z * fRot[8];
|
||||
return global;
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
UVector3 UTransform3D::GlobalVector(const UVector3& local) const
|
||||
{
|
||||
// Returns vector components converted from the local frame defined by the
|
||||
// transformation to the global one. This is defined by multiplying this
|
||||
// transformation with the local vector while ignoring the translation.
|
||||
UVector3 global(
|
||||
local.x * fRot[0] + local.y * fRot[1] + local.z * fRot[2],
|
||||
local.x * fRot[3] + local.y * fRot[4] + local.z * fRot[5],
|
||||
local.x * fRot[6] + local.y * fRot[7] + local.z * fRot[8]);
|
||||
|
||||
return global;
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
UVector3 UTransform3D::LocalPoint(const UVector3& global) const
|
||||
{
|
||||
// Returns local point coordinates converted from the global frame defined
|
||||
// by the transformation. This is defined by multiplying the inverse
|
||||
// transformation with the global vector.
|
||||
UVector3 mt = global - fTr;
|
||||
UVector3 local(
|
||||
mt.x * fRot[0] + mt.y * fRot[3] + mt.z * fRot[6],
|
||||
mt.x * fRot[1] + mt.y * fRot[4] + mt.z * fRot[7],
|
||||
mt.x * fRot[2] + mt.y * fRot[5] + mt.z * fRot[8]);
|
||||
return local;
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
UVector3 UTransform3D::LocalVector(const UVector3& global) const
|
||||
{
|
||||
// Returns local point coordinates converted from the global frame defined
|
||||
// by the transformation. This is defined by multiplying the inverse
|
||||
// transformation with the global vector.
|
||||
UVector3 local(
|
||||
global.x * fRot[0] + global.y * fRot[3] + global.z * fRot[6],
|
||||
global.x * fRot[1] + global.y * fRot[4] + global.z * fRot[7],
|
||||
global.x * fRot[2] + global.y * fRot[5] + global.z * fRot[8]);
|
||||
|
||||
return local;
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
UTransform3D& UTransform3D::operator *= (const UTransform3D& other)
|
||||
{
|
||||
// Multiply with other transformation.
|
||||
fTr.x = fRot[0] * other.fTr[0] + fRot[1] * other.fTr[1] + fRot[2] * other.fTr[2];
|
||||
fTr.y = fRot[3] * other.fTr[0] + fRot[4] * other.fTr[1] + fRot[5] * other.fTr[2];
|
||||
fTr.z = fRot[6] * other.fTr[0] + fRot[7] * other.fTr[1] + fRot[8] * other.fTr[2];
|
||||
|
||||
double newrot[9];
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
for (int j = 0; j < 3; j++)
|
||||
{
|
||||
newrot[3 * i + j] = fRot[3 * i] * other.fRot[j] +
|
||||
fRot[3 * i + 1] * other.fRot[3 + j] +
|
||||
fRot[3 * i + 2] * other.fRot[6 + j];
|
||||
}
|
||||
}
|
||||
std::memcpy(fRot, newrot, sizeof(kIdRot));
|
||||
return *this;
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
UTransform3D& UTransform3D::operator *= (const UVector3& vect)
|
||||
{
|
||||
// Multiply with a vector.
|
||||
fTr.x = fRot[0] * vect.x + fRot[1] * vect.y + fRot[2] * vect.z;
|
||||
fTr.y = fRot[3] * vect.x + fRot[4] * vect.y + fRot[5] * vect.z;
|
||||
fTr.z = fRot[6] * vect.x + fRot[7] * vect.y + fRot[8] * vect.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
UVector3 operator * (const UVector3& /*p*/, const UTransform3D& /*trans*/)
|
||||
{
|
||||
// Multiply matrix with translation.
|
||||
UVector3 vect;
|
||||
return vect;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,288 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UUtils
|
||||
//
|
||||
// 19.10.12 Marek Gayer
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include "UVector3.hh"
|
||||
#include "UTransform3D.hh"
|
||||
#include "UUtils.hh"
|
||||
#include "VUSolid.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
//______________________________________________________________________________
|
||||
void UUtils::TransformLimits(UVector3& min, UVector3& max, const UTransform3D& transformation)
|
||||
{
|
||||
// The goal of this method is to convert the quantities min and max (representing the
|
||||
// bounding box of a given solid in its local frame) to the main frame, using
|
||||
// "transformation"
|
||||
UVector3 vertices[8] = // Detemination of the vertices thanks to the extension of each solid:
|
||||
{
|
||||
UVector3(min.x, min.y, min.z), // 1st vertice:
|
||||
UVector3(min.x, max.y, min.z), // 2nd vertice:
|
||||
UVector3(max.x, max.y, min.z),
|
||||
UVector3(max.x, min.y, min.z),
|
||||
UVector3(min.x, min.y, max.z),
|
||||
UVector3(min.x, max.y, max.z),
|
||||
UVector3(max.x, max.y, max.z),
|
||||
UVector3(max.x, min.y, max.z)
|
||||
};
|
||||
|
||||
min.Set(kInfinity);
|
||||
max.Set(-kInfinity);
|
||||
|
||||
// Loop on th vertices
|
||||
int limit = sizeof(vertices) / sizeof(UVector3);
|
||||
for (int i = 0 ; i < limit; i++)
|
||||
{
|
||||
// From local frame to the gobal one:
|
||||
// Current positions on the three axis:
|
||||
UVector3 current = transformation.GlobalPoint(vertices[i]);
|
||||
|
||||
// If need be, replacement of the min & max values:
|
||||
if (current.x > max.x) max.x = current.x;
|
||||
if (current.x < min.x) min.x = current.x;
|
||||
|
||||
if (current.y > max.y) max.y = current.y;
|
||||
if (current.y < min.y) min.y = current.y;
|
||||
|
||||
if (current.z > max.z) max.z = current.z;
|
||||
if (current.z < min.z) min.z = current.z;
|
||||
}
|
||||
}
|
||||
|
||||
double UUtils::Random(double min, double max)
|
||||
{
|
||||
// srand((unsigned)time(NULL));
|
||||
double number = (double) rand() / RAND_MAX;
|
||||
double res = min + number * (max - min);
|
||||
return res;
|
||||
}
|
||||
|
||||
int UUtils::SaveVectorToExternalFile(const vector<double>& vector, const string& filename)
|
||||
{
|
||||
ofstream file(filename.c_str());
|
||||
|
||||
// NEW: set precision, use exponential, precision 4 digits
|
||||
if (file.is_open())
|
||||
{
|
||||
int size = vector.size();
|
||||
file.precision(16);
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
double value = vector[i];
|
||||
file << value << "\n";
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int UUtils::SaveVectorToExternalFile(const vector<int>& vector, const string& filename)
|
||||
{
|
||||
ofstream file(filename.c_str());
|
||||
|
||||
if (file.is_open())
|
||||
{
|
||||
int size = vector.size();
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
int value = vector[i];
|
||||
file << value << "\n";
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int UUtils::SaveVectorToExternalFile(const vector<UVector3>& vector, const string& filename)
|
||||
{
|
||||
ofstream file(filename.c_str());
|
||||
|
||||
if (file.is_open())
|
||||
{
|
||||
int size = vector.size();
|
||||
file.precision(16);
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
const UVector3& vec = vector[i];
|
||||
file << vec.x << "\t" << vec.y << "\t" << vec.z << "\n";
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
string UUtils::ToString(int number)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << number;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
string UUtils::ToString(double number)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << number;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
int UUtils::FileSize(const std::string& filePath)
|
||||
{
|
||||
std::streampos fsize = 0;
|
||||
std::ifstream file(filePath.c_str(), std::ios::binary);
|
||||
|
||||
fsize = file.tellg();
|
||||
file.seekg(0, std::ios::end);
|
||||
fsize = file.tellg() - fsize;
|
||||
file.close();
|
||||
|
||||
return fsize;
|
||||
}
|
||||
|
||||
|
||||
int UUtils::StrPos(const string& haystack, const string& needle)
|
||||
{
|
||||
int sleng = haystack.length();
|
||||
int nleng = needle.length();
|
||||
|
||||
if (sleng == 0 || nleng == 0)
|
||||
return -1;
|
||||
|
||||
for (int i = 0, j = 0; i < sleng; j = 0, i++)
|
||||
{
|
||||
while (i + j < sleng && j < nleng && haystack[i + j] == needle[j])
|
||||
j++;
|
||||
if (j == nleng)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
void UUtils:: Exception(const char* originOfException,
|
||||
const char* exceptionCode,
|
||||
ExceptionSeverity severity,
|
||||
int level,
|
||||
const char* description)
|
||||
|
||||
{
|
||||
bool toBeAborted = true;
|
||||
static const std::string es_banner
|
||||
= "\n-------- EEEE ------- UException-START -------- EEEE -------\n";
|
||||
static const std::string ee_banner
|
||||
= "\n-------- EEEE ------- UException-END --------- EEEE -------\n";
|
||||
static const std::string ws_banner
|
||||
= "\n-------- WWWW ------- UException-START -------- WWWW -------\n";
|
||||
static const std::string we_banner
|
||||
= "\n-------- WWWW -------- UException-END --------- WWWW -------\n";
|
||||
std::ostringstream message;
|
||||
message << "\n*** ExceptionHandler is not defined ***\n"
|
||||
<< "*** Exception : " << exceptionCode << std::endl
|
||||
<< " issued by : " << originOfException << std::endl
|
||||
<< description << std::endl;
|
||||
switch (severity)
|
||||
{
|
||||
case FatalError:
|
||||
std::cerr << es_banner << message.str() << "*** Fatal Exception ***"
|
||||
<< ee_banner << std::endl;
|
||||
break;
|
||||
case FatalErrorInArguments:
|
||||
std::cerr << es_banner << message.str() << "*** Fatal Error In Argument ***"
|
||||
<< ee_banner << std::endl;
|
||||
break;
|
||||
case Error:
|
||||
std::cerr << es_banner << message.str() << "*** Error ***" << level
|
||||
<< ee_banner << std::endl;
|
||||
break;
|
||||
case Warning:
|
||||
std::cerr << ws_banner << message.str() << "*** This is just a warning message ***"
|
||||
<< we_banner << std::endl;
|
||||
toBeAborted = false;
|
||||
break;
|
||||
default:
|
||||
std::cout << ws_banner << message.str()
|
||||
<< "*** This is just a message for your information. ***"
|
||||
<< we_banner << std::endl;
|
||||
toBeAborted = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (toBeAborted)
|
||||
{
|
||||
|
||||
std::cerr << std::endl << "*** GException: Aborting execution ***" << std::endl;
|
||||
abort();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
void UTessellatedSolid::ImportFromSTLFile(std::string filename)
|
||||
{
|
||||
vector <UTriangularFacet *> fFacets;
|
||||
|
||||
USTL::ReadFromBinaryFile(filename, fFacets);
|
||||
|
||||
int size = fFacets.size();
|
||||
for (int i = 0; i < size; ++i)
|
||||
{
|
||||
UTriangularFacet *facet = fFacets[i];
|
||||
AddFacet(facet);
|
||||
}
|
||||
SetSolidClosed(true);
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
int size = fFacets.size();
|
||||
for (int j = 0; j < 100; ++j) //2.418 , 2.511
|
||||
for (int i = 0; i < size; ++i)
|
||||
{
|
||||
UFacet &facet = *facetsi[j];
|
||||
a += facet.GetNumberOfVertices();
|
||||
}
|
||||
if (a % rand() == -1) cout << a;
|
||||
*/
|
||||
|
||||
/*
|
||||
for (int j = 0; j < 100; ++j) //2.917 3.01
|
||||
{
|
||||
int size = fFacets.size();
|
||||
for (int i = 0; i < size; ++i)
|
||||
{
|
||||
UFacet &facet = *fFacets[i];
|
||||
a += facet.GetNumberOfVertices();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
for (int j = 0; j < 100; ++j) // 2.589
|
||||
{
|
||||
std::vector<UFacet *>::const_iterator i, begin = fFacets.begin(), end = fFacets.end();
|
||||
for (i = begin; i < end; ++i)
|
||||
{
|
||||
UFacet &facet = *(*i);
|
||||
a += facet.GetNumberOfVertices();
|
||||
}
|
||||
}
|
||||
|
||||
return location;
|
||||
*/
|
||||
@@ -0,0 +1,955 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UVCSGfaceted
|
||||
//
|
||||
// 19.09.13 Marek Gayer
|
||||
// Created from original implementation in Geant4
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#include "UUtils.hh"
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
#include <sstream>
|
||||
#include "UVCSGfaceted.hh"
|
||||
#include "UVCSGface.hh"
|
||||
#include "UVoxelizer.hh"
|
||||
#include "UReduciblePolygon.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
//
|
||||
// Constructor
|
||||
//
|
||||
UVCSGfaceted::UVCSGfaceted(const std::string& name)
|
||||
: VUSolid(name),
|
||||
numFace(0), faces(0), fCubicVolume(0.), fSurfaceArea(0.),
|
||||
fMaxSection(0),fBoxShift(0.), fNoVoxels(true),fStatistics(1000000), fCubVolEpsilon(0.001), fAreaAccuracy(-1.)
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Destructor
|
||||
//
|
||||
UVCSGfaceted::~UVCSGfaceted()
|
||||
{
|
||||
DeleteStuff();
|
||||
}
|
||||
|
||||
//
|
||||
// Copy constructor
|
||||
//
|
||||
UVCSGfaceted::UVCSGfaceted(const UVCSGfaceted& source)
|
||||
: VUSolid(source)
|
||||
{
|
||||
fStatistics = source.fStatistics;
|
||||
fCubVolEpsilon = source.fCubVolEpsilon;
|
||||
fAreaAccuracy = source.fAreaAccuracy;
|
||||
|
||||
CopyStuff(source);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Assignment operator
|
||||
//
|
||||
UVCSGfaceted& UVCSGfaceted::operator=(const UVCSGfaceted& source)
|
||||
{
|
||||
if (&source == this)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Copy base class data
|
||||
//
|
||||
VUSolid::operator=(source);
|
||||
|
||||
// Copy data
|
||||
//
|
||||
fStatistics = source.fStatistics;
|
||||
fCubVolEpsilon = source.fCubVolEpsilon;
|
||||
fAreaAccuracy = source.fAreaAccuracy;
|
||||
|
||||
CopyStuff(source);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// CopyStuff (protected)
|
||||
//
|
||||
// Copy the contents of source
|
||||
//
|
||||
void UVCSGfaceted::CopyStuff(const UVCSGfaceted& source)
|
||||
{
|
||||
numFace = source.numFace;
|
||||
if (numFace == 0)
|
||||
{
|
||||
return; // odd, but permissable?
|
||||
}
|
||||
|
||||
faces = new UVCSGface*[numFace];
|
||||
|
||||
UVCSGface** face = faces,
|
||||
**sourceFace = source.faces;
|
||||
do
|
||||
{
|
||||
*face = (*sourceFace)->Clone();
|
||||
}
|
||||
while (++sourceFace, ++face < faces + numFace);
|
||||
fCubicVolume = source.fCubicVolume;
|
||||
fSurfaceArea = source.fSurfaceArea;
|
||||
|
||||
fMaxSection = source.fMaxSection;
|
||||
fNoVoxels = source.fNoVoxels;
|
||||
fZs = source.fZs;
|
||||
fBox = source.fBox;
|
||||
fBoxShift = source.fBoxShift;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// DeleteStuff (protected)
|
||||
//
|
||||
// Delete all allocated objects
|
||||
//
|
||||
void UVCSGfaceted::DeleteStuff()
|
||||
{
|
||||
if (numFace)
|
||||
{
|
||||
UVCSGface** face = faces;
|
||||
do
|
||||
{
|
||||
delete *face;
|
||||
}
|
||||
while (++face < faces + numFace);
|
||||
|
||||
delete [] faces;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Inside
|
||||
//
|
||||
// It could be a good idea to override this virtual
|
||||
// member to add first a simple test (such as spherical
|
||||
// test or whatnot) and to call this version only if
|
||||
// the simplier test fails.
|
||||
//
|
||||
|
||||
/*
|
||||
VUSolid::EnumInside UVCSGfaceted::Inside( const UVector3 &p ) const
|
||||
{
|
||||
VUSolid::EnumInside answer=eOutside;
|
||||
UVCSGface **face = faces;
|
||||
double best = UUtils::kInfinity;
|
||||
do
|
||||
{
|
||||
double distance;
|
||||
VUSolid::EnumInside result = (*face)->Inside( p, fgTolerance*0.5, &distance );
|
||||
if (result == eSurface) { return eSurface; }
|
||||
if (distance < best)
|
||||
{
|
||||
best = distance;
|
||||
answer = result;
|
||||
}
|
||||
} while( ++face < faces + numFace );
|
||||
|
||||
return answer;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
//
|
||||
// Inside
|
||||
//
|
||||
// It could be a good idea to override this virtual
|
||||
// member to add first a simple test (such as spherical
|
||||
// test or whatnot) and to call this version only if
|
||||
// the simplier test fails.
|
||||
//
|
||||
inline VUSolid::EnumInside UVCSGfaceted::InsideNoVoxels(const UVector3& p) const
|
||||
{
|
||||
VUSolid::EnumInside answer = eOutside;
|
||||
UVCSGface** face = faces;
|
||||
double best = UUtils::kInfinity;
|
||||
do
|
||||
{
|
||||
double distance;
|
||||
VUSolid::EnumInside result = (*face)->Inside(p, fgTolerance * 0.5, &distance);
|
||||
if (result == eSurface)
|
||||
{
|
||||
return eSurface;
|
||||
}
|
||||
if (distance < best)
|
||||
{
|
||||
best = distance;
|
||||
answer = result;
|
||||
}
|
||||
}
|
||||
while (++face < faces + numFace);
|
||||
|
||||
return answer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// SurfaceNormal
|
||||
//
|
||||
|
||||
bool UVCSGfaceted::Normal(const UVector3& p, UVector3& n) const
|
||||
{
|
||||
UVector3 answer;
|
||||
double best = UUtils::kInfinity;
|
||||
UVector3 normal;
|
||||
|
||||
UBits bits(numFace);
|
||||
|
||||
int index = GetSection(p.z);
|
||||
const vector<int>& candidates = fCandidates[index];
|
||||
int size = candidates.size();
|
||||
for (int i = 0; i < size; ++i)
|
||||
{
|
||||
int candidate = candidates[i];
|
||||
if (!bits[candidate])
|
||||
{
|
||||
bits.SetBitNumber(candidate);
|
||||
UVCSGface& face = *faces[candidate];
|
||||
double distance;
|
||||
normal = face.Normal(p, &distance);
|
||||
if (distance < best)
|
||||
{
|
||||
best = distance;
|
||||
answer = normal;
|
||||
if (distance < fgTolerance)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
n = answer;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
// non voxelized version:
|
||||
|
||||
bool UVCSGfaceted::Normal( const UVector3 &p, UVector3 &n) const
|
||||
{
|
||||
UVector3 answer;
|
||||
double best = UUtils::kInfinity;
|
||||
UVector3 normal;
|
||||
|
||||
for (int i = 0; i < numFace; ++i)
|
||||
{
|
||||
UVCSGface &face = *faces[i];
|
||||
double distance;
|
||||
normal = face.Normal( p, &distance);
|
||||
if (distance < best)
|
||||
{
|
||||
best = distance;
|
||||
answer = normal;
|
||||
}
|
||||
}
|
||||
n = answer;
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
//
|
||||
// DistanceToIn(p,v)
|
||||
//
|
||||
|
||||
inline double UVCSGfaceted::DistanceToInNoVoxels(const UVector3& p,
|
||||
const UVector3& v) const
|
||||
{
|
||||
double distance = UUtils::kInfinity;
|
||||
double distFromSurface = UUtils::kInfinity;
|
||||
UVCSGface** face = faces;
|
||||
UVCSGface* bestFace = *face;
|
||||
static double htol = fgTolerance * 0.5;
|
||||
UVector3 faceNormal;
|
||||
|
||||
do
|
||||
{
|
||||
double faceDistance, faceDistFromSurface;
|
||||
bool faceAllBehind;
|
||||
if ((*face)->Distance(p, v, false, htol,
|
||||
faceDistance, faceDistFromSurface,
|
||||
faceNormal, faceAllBehind))
|
||||
{
|
||||
//
|
||||
// Intersecting face
|
||||
//
|
||||
if (faceDistance < distance)
|
||||
{
|
||||
distance = faceDistance;
|
||||
distFromSurface = faceDistFromSurface;
|
||||
bestFace = *face;
|
||||
if (distFromSurface <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while (++face < faces + numFace);
|
||||
|
||||
if (distance < UUtils::kInfinity && distFromSurface < htol)
|
||||
{
|
||||
if (bestFace->Safety(p, false) < htol)
|
||||
{
|
||||
distance = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return distance;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// DistanceToOut(p,v)
|
||||
//
|
||||
|
||||
inline double UVCSGfaceted::DistanceToOutNoVoxels(const UVector3& p, const UVector3& v, UVector3& n, bool& aConvex) const
|
||||
{
|
||||
bool allBehind = true;
|
||||
double distance = UUtils::kInfinity;
|
||||
double distFromSurface = UUtils::kInfinity;
|
||||
UVector3 normal, faceNormal;
|
||||
|
||||
UVCSGface** face = faces;
|
||||
UVCSGface* bestFace = *face;
|
||||
do
|
||||
{
|
||||
double faceDistance, faceDistFromSurface;
|
||||
bool faceAllBehind;
|
||||
if ((*face)->Distance(p, v, true, fgTolerance / 2,
|
||||
faceDistance, faceDistFromSurface,
|
||||
faceNormal, faceAllBehind))
|
||||
{
|
||||
// Intersecting face
|
||||
if ((distance < UUtils::kInfinity) || (!faceAllBehind))
|
||||
{
|
||||
allBehind = false;
|
||||
}
|
||||
if (faceDistance < distance)
|
||||
{
|
||||
distance = faceDistance;
|
||||
distFromSurface = faceDistFromSurface;
|
||||
normal = faceNormal;
|
||||
bestFace = *face;
|
||||
if (distFromSurface <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while (++face < faces + numFace);
|
||||
|
||||
if (distance < UUtils::kInfinity)
|
||||
{
|
||||
if (distFromSurface <= 0)
|
||||
{
|
||||
distance = 0;
|
||||
}
|
||||
else if (distFromSurface < fgTolerance / 2)
|
||||
{
|
||||
if (bestFace->Safety(p, true) < fgTolerance / 2)
|
||||
{
|
||||
distance = 0;
|
||||
}
|
||||
}
|
||||
|
||||
aConvex = allBehind;
|
||||
n = normal;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Inside(p) == eSurface)
|
||||
{
|
||||
distance = 0;
|
||||
}
|
||||
aConvex = false;
|
||||
}
|
||||
|
||||
return distance;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// DistanceTo
|
||||
//
|
||||
// Protected routine called by DistanceToIn and DistanceToOut
|
||||
//
|
||||
double UVCSGfaceted::DistanceTo(const UVector3& p,
|
||||
const bool outgoing) const
|
||||
{
|
||||
UVCSGface** face = faces;
|
||||
double best = UUtils::kInfinity;
|
||||
do
|
||||
{
|
||||
double distance = (*face)->Safety(p, outgoing);
|
||||
if (distance < best) best = distance;
|
||||
}
|
||||
while (++face < faces + numFace);
|
||||
|
||||
return (best < 0.5 * fgTolerance) ? 0 : best;
|
||||
}
|
||||
|
||||
//
|
||||
// GetEntityType
|
||||
//
|
||||
UGeometryType UVCSGfaceted::GetEntityType() const
|
||||
{
|
||||
return std::string("UCSGfaceted");
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Stream object contents to an output stream
|
||||
//
|
||||
std::ostream& UVCSGfaceted::StreamInfo(std::ostream& os) const
|
||||
{
|
||||
os << "-----------------------------------------------------------\n"
|
||||
<< " *** Dump for solid - " << GetName() << " ***\n"
|
||||
<< " ===================================================\n"
|
||||
<< " Solid type: UVCSGfaceted\n"
|
||||
<< " Parameters: \n"
|
||||
<< " number of faces: " << numFace << "\n"
|
||||
<< "-----------------------------------------------------------\n";
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// GetCubVolStatistics
|
||||
//
|
||||
int UVCSGfaceted::GetCubVolStatistics() const
|
||||
{
|
||||
return fStatistics;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// GetCubVolEpsilon
|
||||
//
|
||||
double UVCSGfaceted::GetCubVolEpsilon() const
|
||||
{
|
||||
return fCubVolEpsilon;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// SetCubVolStatistics
|
||||
//
|
||||
void UVCSGfaceted::SetCubVolStatistics(int st)
|
||||
{
|
||||
fCubicVolume = 0.;
|
||||
fStatistics = st;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// SetCubVolEpsilon
|
||||
//
|
||||
void UVCSGfaceted::SetCubVolEpsilon(double ep)
|
||||
{
|
||||
fCubicVolume = 0.;
|
||||
fCubVolEpsilon = ep;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// GetAreaStatistics
|
||||
//
|
||||
int UVCSGfaceted::GetAreaStatistics() const
|
||||
{
|
||||
return fStatistics;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// GetAreaAccuracy
|
||||
//
|
||||
double UVCSGfaceted::GetAreaAccuracy() const
|
||||
{
|
||||
return fAreaAccuracy;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// SetAreaStatistics
|
||||
//
|
||||
void UVCSGfaceted::SetAreaStatistics(int st)
|
||||
{
|
||||
fSurfaceArea = 0.;
|
||||
fStatistics = st;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// SetAreaAccuracy
|
||||
//
|
||||
void UVCSGfaceted::SetAreaAccuracy(double ep)
|
||||
{
|
||||
fSurfaceArea = 0.;
|
||||
fAreaAccuracy = ep;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Capacity
|
||||
//
|
||||
double UVCSGfaceted::Capacity()
|
||||
{
|
||||
if (fCubicVolume != 0.)
|
||||
{
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
fCubicVolume = EstimateCubicVolume(fStatistics, fCubVolEpsilon);
|
||||
}
|
||||
return fCubicVolume;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// SurfaceArea
|
||||
//
|
||||
double UVCSGfaceted::SurfaceArea()
|
||||
{
|
||||
if (fSurfaceArea != 0.)
|
||||
{
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
fSurfaceArea = EstimateSurfaceArea(fStatistics, fAreaAccuracy);
|
||||
}
|
||||
return fSurfaceArea;
|
||||
}
|
||||
|
||||
//
|
||||
// GetPointOnSurfaceGeneric proportional to Areas of faces
|
||||
// in case of GenericPolycone or GenericPolyhedra
|
||||
//
|
||||
UVector3 UVCSGfaceted::GetPointOnSurfaceGeneric() const
|
||||
{
|
||||
// Preparing variables
|
||||
//
|
||||
UVector3 answer = UVector3(0., 0., 0.);
|
||||
UVCSGface** face = faces;
|
||||
double area = 0;
|
||||
int i;
|
||||
std::vector<double> areas;
|
||||
|
||||
// First step: calculate surface areas
|
||||
//
|
||||
do
|
||||
{
|
||||
double result = (*face)->SurfaceArea();
|
||||
areas.push_back(result);
|
||||
area = area + result;
|
||||
}
|
||||
while (++face < faces + numFace);
|
||||
|
||||
// Second Step: choose randomly one surface
|
||||
//
|
||||
UVCSGface** face1 = faces;
|
||||
double chose = area * UUtils::Random();
|
||||
double Achose1, Achose2;
|
||||
Achose1 = 0;
|
||||
Achose2 = 0.;
|
||||
i = 0;
|
||||
|
||||
do
|
||||
{
|
||||
Achose2 += areas[i];
|
||||
if (chose >= Achose1 && chose < Achose2)
|
||||
{
|
||||
UVector3 point;
|
||||
point = (*face1)->GetPointOnFace();
|
||||
return point;
|
||||
}
|
||||
i++;
|
||||
Achose1 = Achose2;
|
||||
}
|
||||
while (++face1 < faces + numFace);
|
||||
|
||||
return answer;
|
||||
}
|
||||
|
||||
double UVCSGfaceted::SafetyFromOutside(const UVector3& p, bool accurate) const
|
||||
{
|
||||
if (!accurate)
|
||||
{
|
||||
UVector3 pb(p.x, p.y, p.z - fBoxShift);
|
||||
return fBox.SafetyFromOutside(pb);
|
||||
}
|
||||
return DistanceTo(p, false);
|
||||
}
|
||||
|
||||
double UVCSGfaceted::SafetyFromInsideNoVoxels(const UVector3& p, bool) const
|
||||
{
|
||||
return DistanceTo(p, true);
|
||||
}
|
||||
|
||||
|
||||
void UVCSGfaceted::InitVoxels(UReduciblePolygon& rz, double radius)
|
||||
{
|
||||
int size = rz.NumVertices() + 1;
|
||||
vector<double> r(size), z(size), zs;
|
||||
rz.CopyVertices(&r[0], &z[0]);
|
||||
|
||||
fZs.clear();
|
||||
for (int i = 0; i < size; ++i)
|
||||
{
|
||||
double v = z[i];
|
||||
if (std::find(fZs.begin(), fZs.end(), v) == fZs.end())
|
||||
{
|
||||
fZs.push_back(v);
|
||||
}
|
||||
std::sort(fZs.begin(), fZs.end());
|
||||
}
|
||||
|
||||
size = fZs.size();
|
||||
fMaxSection = size - 2;
|
||||
|
||||
for (int i = 0; i <= fMaxSection; ++i)
|
||||
{
|
||||
vector<int> candidates;
|
||||
|
||||
double left = fZs[i], right = fZs[i + 1];
|
||||
double middle = (left + right) / 2;
|
||||
FindCandidates(middle, candidates);
|
||||
|
||||
FindCandidates(left, candidates, true);
|
||||
FindCandidates(right, candidates, true);
|
||||
|
||||
fCandidates.push_back(candidates);
|
||||
}
|
||||
|
||||
fBox.Set(radius, radius, (fZs.back() - fZs.front()) / 2);
|
||||
fBoxShift = fZs[0] + fBox.GetZHalfLength();
|
||||
}
|
||||
|
||||
void UVCSGfaceted::FindCandidates(double z, vector <int>& candidates, bool sides)
|
||||
{
|
||||
for (int j = 0; j < numFace; j++)
|
||||
{
|
||||
UVCSGface* face = faces[j];
|
||||
double minZ = -face->Extent(UVector3(0, 0, -1)) ;
|
||||
double maxZ = face->Extent(UVector3(0, 0, 1));
|
||||
if (z >= minZ - fgTolerance * 10 && z <= maxZ + fgTolerance * 10)
|
||||
{
|
||||
if (!sides || std::fabs(minZ - maxZ) < fgTolerance * 10)
|
||||
if (std::find(candidates.begin(), candidates.end(), j) == candidates.end())
|
||||
candidates.push_back(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
double UVCSGfaceted::DistanceToIn(const UVector3& p, const UVector3& v, double /*aPstep*/) const
|
||||
{
|
||||
if (fNoVoxels) return DistanceToInNoVoxels(p, v);
|
||||
|
||||
UVector3 pb(p.x, p.y, p.z - fBoxShift);
|
||||
|
||||
double idistance, shift;
|
||||
idistance = fBox.DistanceToIn(pb, v); // using only box, this appears
|
||||
// to be faster than: idistance = enclosingCylinder->DistanceTo(pb, v);
|
||||
if (idistance >= UUtils::kInfinity) return idistance;
|
||||
|
||||
// this line can be here or not. not a big difference in performance
|
||||
// TODO: fix enclosingCylinder for polyhedra!!! - the current radius appears to be too small
|
||||
// if (enclosingCylinder->ShouldMiss(p, v)) return UUtils::kInfinity;
|
||||
|
||||
// this just takes too much time
|
||||
// idistance = enclosingCylinder->DistanceTo(pb, v);
|
||||
// if (idistance == UUtils::kInfinity) return idistance;
|
||||
|
||||
double z = p.z + idistance * v.z;
|
||||
int index = GetSection(z);
|
||||
int increment = (v.z > 0) ? 1 : -1;
|
||||
if (std::fabs(v.z) < fgTolerance) increment = 0;
|
||||
|
||||
double distance = UUtils::kInfinity;
|
||||
double distFromSurface = UUtils::kInfinity;
|
||||
UVCSGface* bestFace = 0;
|
||||
UBits bits(numFace);
|
||||
UVector3 faceNormal;
|
||||
|
||||
do
|
||||
{
|
||||
const vector<int>& candidates = fCandidates[index];
|
||||
int size = candidates.size();
|
||||
for (int i = 0; i < size; ++i)
|
||||
{
|
||||
int candidate = candidates[i];
|
||||
if (!bits[candidate])
|
||||
{
|
||||
bits.SetBitNumber(candidate);
|
||||
UVCSGface& face = *faces[candidate];
|
||||
|
||||
double faceDistance,
|
||||
faceDistFromSurface;
|
||||
bool faceAllBehind;
|
||||
if (face.Distance(p, v, false, fgTolerance * 0.5,
|
||||
faceDistance, faceDistFromSurface,
|
||||
faceNormal, faceAllBehind))
|
||||
{
|
||||
// Intersecting face
|
||||
if (faceDistance < distance)
|
||||
{
|
||||
distance = faceDistance;
|
||||
distFromSurface = faceDistFromSurface;
|
||||
bestFace = &face;
|
||||
if (distFromSurface <= 0) return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!increment)
|
||||
break;
|
||||
|
||||
index += increment;
|
||||
if (index < 0 || index > fMaxSection)
|
||||
break;
|
||||
int newz = increment > 0 ? index : index + 1;
|
||||
shift = (fZs[newz] - z) / v.z;
|
||||
}
|
||||
while (idistance + shift < distance);
|
||||
|
||||
if (distance < UUtils::kInfinity && distFromSurface < fgTolerance / 2)
|
||||
{
|
||||
if (bestFace->Safety(p, false) < fgTolerance / 2)
|
||||
{
|
||||
distance = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return distance;
|
||||
}
|
||||
|
||||
|
||||
|
||||
double UVCSGfaceted::DistanceToOut(const UVector3& p, const UVector3& v, UVector3& n, bool& aConvex, double /*aPstep*/) const
|
||||
{
|
||||
if (fNoVoxels) return DistanceToOutNoVoxels(p, v, n, aConvex);
|
||||
|
||||
int index = GetSection(p.z);
|
||||
int increment = (v.z > 0) ? 1 : -1;
|
||||
|
||||
bool allBehind = true;
|
||||
double distance = UUtils::kInfinity;
|
||||
double distFromSurface = UUtils::kInfinity;
|
||||
UVector3 normal, faceNormal;
|
||||
double shift;
|
||||
|
||||
UVCSGface* bestFace = 0;
|
||||
UBits bits(numFace);
|
||||
|
||||
do
|
||||
{
|
||||
const vector<int>& candidates = fCandidates[index];
|
||||
int size = candidates.size();
|
||||
for (int i = 0; i < size; ++i)
|
||||
{
|
||||
int candidate = candidates[i];
|
||||
if (!bits[candidate])
|
||||
{
|
||||
bits.SetBitNumber(candidate);
|
||||
UVCSGface& face = *faces[candidate];
|
||||
|
||||
double faceDistance, faceDistFromSurface;
|
||||
bool faceAllBehind;
|
||||
if ((face.Distance(p, v, true, fgTolerance * 0.5, faceDistance, faceDistFromSurface,
|
||||
faceNormal, faceAllBehind)))
|
||||
{
|
||||
// Intersecting face
|
||||
if ((distance < UUtils::kInfinity) || (!faceAllBehind))
|
||||
{
|
||||
allBehind = false;
|
||||
}
|
||||
if (faceDistance < distance)
|
||||
{
|
||||
distance = faceDistance;
|
||||
distFromSurface = faceDistFromSurface;
|
||||
normal = faceNormal;
|
||||
bestFace = &face;
|
||||
if (distFromSurface <= 0) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (distFromSurface <= 0) break;
|
||||
if (!increment) break;
|
||||
|
||||
index += increment;
|
||||
if (index < 0 || index > fMaxSection)
|
||||
break;
|
||||
int newz = increment > 0 ? index : index + 1;
|
||||
shift = (fZs[newz] - p.z) / v.z;
|
||||
}
|
||||
while (shift < distance);
|
||||
|
||||
if (distance < UUtils::kInfinity)
|
||||
{
|
||||
if (distFromSurface <= 0)
|
||||
{
|
||||
distance = 0;
|
||||
}
|
||||
else if (distFromSurface < fgTolerance / 2)
|
||||
{
|
||||
if (bestFace->Safety(p, true) < fgTolerance * 0.5)
|
||||
{
|
||||
distance = 0;
|
||||
}
|
||||
}
|
||||
|
||||
aConvex = allBehind;
|
||||
n = normal;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Inside(p) == eSurface)
|
||||
{
|
||||
distance = 0;
|
||||
}
|
||||
aConvex = false;
|
||||
}
|
||||
|
||||
return distance;
|
||||
}
|
||||
|
||||
|
||||
VUSolid::EnumInside UVCSGfaceted::Inside(const UVector3& p) const
|
||||
{
|
||||
if (fNoVoxels) return InsideNoVoxels(p);
|
||||
|
||||
// if (fEnclosingCylinder->MustBeOutside(p)) return eOutside;
|
||||
|
||||
int index = GetSection(p.z);
|
||||
double shift;
|
||||
|
||||
UBits bits(numFace);
|
||||
double best = UUtils::kInfinity;
|
||||
VUSolid::EnumInside answer = eOutside;
|
||||
int middle = index;
|
||||
|
||||
do
|
||||
{
|
||||
const vector<int>& candidates = fCandidates[index];
|
||||
int size = candidates.size();
|
||||
for (int i = 0; i < size; ++i)
|
||||
{
|
||||
int candidate = candidates[i];
|
||||
if (!bits[candidate])
|
||||
{
|
||||
UVCSGface& face = *faces[candidate];
|
||||
|
||||
double distance;
|
||||
VUSolid::EnumInside result = face.Inside(p, fgTolerance * 0.5, &distance);
|
||||
if (result == eSurface) return eSurface;
|
||||
if (distance < best)
|
||||
{
|
||||
best = distance;
|
||||
answer = result;
|
||||
}
|
||||
bits.SetBitNumber(candidate);
|
||||
}
|
||||
}
|
||||
|
||||
if (index <= middle)
|
||||
{
|
||||
if (--index >= 0)
|
||||
{
|
||||
shift = fZs[index + 1] - p.z;
|
||||
if (shift < best) continue;
|
||||
}
|
||||
index = middle;
|
||||
}
|
||||
if (++index > fMaxSection) break;
|
||||
shift = p.z - fZs[index];
|
||||
}
|
||||
while (shift > best);
|
||||
|
||||
return answer;
|
||||
}
|
||||
|
||||
double UVCSGfaceted::SafetyFromInsideSection(int index, const UVector3& p, UBits& bits) const
|
||||
{
|
||||
double best = UUtils::kInfinity;
|
||||
|
||||
const vector<int>& candidates = fCandidates[index];
|
||||
int size = candidates.size();
|
||||
for (int i = 0; i < size; ++i)
|
||||
{
|
||||
int candidate = candidates[i];
|
||||
if (!bits[candidate])
|
||||
{
|
||||
bits.SetBitNumber(candidate);
|
||||
UVCSGface& face = *faces[candidate];
|
||||
|
||||
double distance = face.Safety(p, true);
|
||||
if (distance < best) best = distance;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
double UVCSGfaceted::SafetyFromInside(const UVector3& p, bool) const
|
||||
{
|
||||
if (fNoVoxels) return SafetyFromInsideNoVoxels(p);
|
||||
|
||||
int index = UVoxelizer::BinarySearch(fZs, p.z);
|
||||
if (index < 0 || index > fMaxSection) return 0;
|
||||
|
||||
UBits bits(numFace);
|
||||
double minSafety = SafetyFromInsideSection(index, p, bits);
|
||||
|
||||
if (minSafety > UUtils::kInfinity) return 0;
|
||||
if (minSafety < 1e-6) return 0;
|
||||
|
||||
double zbase = fZs[index + 1];
|
||||
for (int i = index + 1; i <= fMaxSection; ++i)
|
||||
{
|
||||
double dz = fZs[i] - zbase;
|
||||
if (dz >= minSafety) break;
|
||||
double safety = SafetyFromInsideSection(i, p, bits);
|
||||
if (safety < minSafety) minSafety = safety;
|
||||
}
|
||||
|
||||
if (index > 0)
|
||||
{
|
||||
zbase = fZs[index - 1];
|
||||
for (int i = index - 1; i >= 0; --i)
|
||||
{
|
||||
double dz = zbase - fZs[i];
|
||||
if (dz >= minSafety) break;
|
||||
double safety = SafetyFromInsideSection(i, p, bits);
|
||||
if (safety < minSafety) minSafety = safety;
|
||||
}
|
||||
}
|
||||
return (minSafety < 0.5 * fgTolerance) ? 0 : minSafety;
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UVector2
|
||||
//
|
||||
// 19.09.12 Marek Gayer
|
||||
// Created from original implementation in CLHEP
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include "UVector2.hh"
|
||||
|
||||
double UVector2::tolerance = UVector2::ZMpvToleranceTicks * 2.22045e-16;
|
||||
|
||||
double UVector2::setTolerance(double tol)
|
||||
{
|
||||
// Set the tolerance for UVector2s to be considered near one another
|
||||
double oldTolerance(tolerance);
|
||||
tolerance = tol;
|
||||
return oldTolerance;
|
||||
}
|
||||
|
||||
double UVector2::operator()(int i) const
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
else if (i == 1)
|
||||
{
|
||||
return y;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ZMthrowA(ZMxpvIndexRange("UVector2::operator(): bad index"));
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
double& UVector2::operator()(int i)
|
||||
{
|
||||
static double dummy;
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case X:
|
||||
return x;
|
||||
case Y:
|
||||
return y;
|
||||
default:
|
||||
// ZMthrowA (ZMxpvIndexRange("UVector2::operator() : bad index"));
|
||||
return dummy;
|
||||
}
|
||||
}
|
||||
|
||||
void UVector2::rotate(double angler)
|
||||
{
|
||||
double s = std::sin(angler);
|
||||
double c = std::cos(angler);
|
||||
double xx = x;
|
||||
x = c * xx - s * y;
|
||||
y = s * xx + c * y;
|
||||
}
|
||||
|
||||
UVector2 operator/ (const UVector2& p, double a)
|
||||
{
|
||||
if (a == 0)
|
||||
{
|
||||
// ZMthrowA(ZMxpvInfiniteVector( "Division of UVector2 by zero"));
|
||||
}
|
||||
return UVector2(p.x / a, p.y / a);
|
||||
}
|
||||
|
||||
std::ostream& operator << (std::ostream& os, const UVector2& q)
|
||||
{
|
||||
os << "(" << q.x << ", " << q.y << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
//void ZMinput2doubles ( std::istream & is, const char * type,
|
||||
// double & x, double & y );
|
||||
|
||||
/*
|
||||
std::istream & operator>>(std::istream & is, UVector2 & p) {
|
||||
double x, y;
|
||||
ZMinput2doubles ( is, "UVector2", x, y );
|
||||
p.set(x, y);
|
||||
return is;
|
||||
} // operator>>()
|
||||
*/
|
||||
|
||||
UVector2::operator UVector3() const
|
||||
{
|
||||
return UVector3(x, y, 0.0);
|
||||
}
|
||||
|
||||
int UVector2::compare(const UVector2& v) const
|
||||
{
|
||||
if (y > v.y)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if (y < v.y)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (x > v.x)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if (x < v.x)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
} /* Compare */
|
||||
|
||||
|
||||
bool UVector2::operator > (const UVector2& v) const
|
||||
{
|
||||
return (compare(v) > 0);
|
||||
}
|
||||
bool UVector2::operator < (const UVector2& v) const
|
||||
{
|
||||
return (compare(v) < 0);
|
||||
}
|
||||
bool UVector2::operator>= (const UVector2& v) const
|
||||
{
|
||||
return (compare(v) >= 0);
|
||||
}
|
||||
bool UVector2::operator<= (const UVector2& v) const
|
||||
{
|
||||
return (compare(v) <= 0);
|
||||
}
|
||||
|
||||
bool UVector2::isNear(const UVector2& p, double epsilon) const
|
||||
{
|
||||
double limit = dot(p) * epsilon * epsilon;
|
||||
return ((*this - p).mag2() <= limit);
|
||||
} /* isNear() */
|
||||
|
||||
double UVector2::howNear(const UVector2& p) const
|
||||
{
|
||||
double d = (*this - p).mag2();
|
||||
double pdp = dot(p);
|
||||
if ((pdp > 0) && (d < pdp))
|
||||
{
|
||||
return std::sqrt(d / pdp);
|
||||
}
|
||||
else if ((pdp == 0) && (d == 0))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
} /* howNear */
|
||||
|
||||
double UVector2::howParallel(const UVector2& v) const
|
||||
{
|
||||
// | V1 x V2 | / | V1 dot V2 |
|
||||
// Of course, the "cross product" is fictitious but the math is valid
|
||||
double v1v2 = std::fabs(dot(v));
|
||||
if (v1v2 == 0)
|
||||
{
|
||||
// Zero is parallel to no other vector except for zero.
|
||||
return ((mag2() == 0) && (v.mag2() == 0)) ? 0 : 1;
|
||||
}
|
||||
double abscross = std::fabs(x * v.y - y - v.x);
|
||||
if (abscross >= v1v2)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return abscross / v1v2;
|
||||
}
|
||||
} /* howParallel() */
|
||||
|
||||
bool UVector2::isParallel(const UVector2& v,
|
||||
double epsilon) const
|
||||
{
|
||||
// | V1 x V2 | <= epsilon * | V1 dot V2 |
|
||||
// Of course, the "cross product" is fictitious but the math is valid
|
||||
double v1v2 = std::fabs(dot(v));
|
||||
if (v1v2 == 0)
|
||||
{
|
||||
// Zero is parallel to no other vector except for zero.
|
||||
return ((mag2() == 0) && (v.mag2() == 0));
|
||||
}
|
||||
double abscross = std::fabs(x * v.y - y - v.x);
|
||||
return (abscross <= epsilon * v1v2);
|
||||
} /* isParallel() */
|
||||
|
||||
double UVector2::howOrthogonal(const UVector2& v) const
|
||||
{
|
||||
// | V1 dot V2 | / | V1 x V2 |
|
||||
// Of course, the "cross product" is fictitious but the math is valid
|
||||
double v1v2 = std::fabs(dot(v));
|
||||
if (v1v2 == 0)
|
||||
{
|
||||
return 0; // Even if one or both are 0, they are considered orthogonal
|
||||
}
|
||||
double abscross = std::fabs(x * v.y - y - v.x);
|
||||
if (v1v2 >= abscross)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return v1v2 / abscross;
|
||||
}
|
||||
} /* howOrthogonal() */
|
||||
|
||||
bool UVector2::isOrthogonal(const UVector2& v,
|
||||
double epsilon) const
|
||||
{
|
||||
// | V1 dot V2 | <= epsilon * | V1 x V2 |
|
||||
// Of course, the "cross product" is fictitious but the math is valid
|
||||
double v1v2 = std::fabs(dot(v));
|
||||
double abscross = std::fabs(x * v.y - y - v.x);
|
||||
return (v1v2 <= epsilon * abscross);
|
||||
} /* isOrthogonal() */
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * This Software is part of the AIDA Unified Solids Library package *
|
||||
// * See: https://aidasoft.web.cern.ch/USolids *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// UVector3
|
||||
//
|
||||
// 19.09.12 Marek Gayer
|
||||
// Created from original implementation in CLHEP
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#include "UVector3.hh"
|
||||
#include "UUtils.hh"
|
||||
|
||||
//______________________________________________________________________________
|
||||
UVector3::UVector3(double theta, double phi)
|
||||
{
|
||||
// Creates a unit vector based on theta and phi angles
|
||||
x = std::sin(theta) * std::cos(phi);
|
||||
y = std::sin(theta) * std::sin(phi);
|
||||
z = std::cos(theta);
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
double UVector3::Angle(const UVector3& q) const
|
||||
{
|
||||
// return the angle w.r.t. another 3-vector
|
||||
double ptot2 = Mag2() * q.Mag2();
|
||||
if (ptot2 <= 0)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
double arg = Dot(q) / std::sqrt(ptot2);
|
||||
if (arg > 1.0) arg = 1.0;
|
||||
if (arg < -1.0) arg = -1.0;
|
||||
return UUtils::ACos(arg);
|
||||
}
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
double UVector3::Mag() const
|
||||
{
|
||||
// return the magnitude (rho in spherical coordinate system)
|
||||
|
||||
return std::sqrt(Mag2());
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
double UVector3::Perp() const
|
||||
{
|
||||
//return the transverse component (R in cylindrical coordinate system)
|
||||
|
||||
return std::sqrt(Perp2());
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
double UVector3::Phi() const
|
||||
{
|
||||
//return the azimuth angle. returns phi from -pi to pi
|
||||
return x == 0.0 && y == 0.0 ? 0.0 : UUtils::ATan2(y, x);
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
double UVector3::Theta() const
|
||||
{
|
||||
//return the polar angle from 0 to pi
|
||||
double mag2 = Mag2();
|
||||
if (mag2 == 0.0) return 0.0;
|
||||
return UUtils::ACos(z / std::sqrt(mag2));
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
UVector3 UVector3::Unit() const
|
||||
{
|
||||
// return unit vector parallel to this.
|
||||
double tot = Mag2();
|
||||
UVector3 p(x, y, z);
|
||||
return tot > 0.0 ? p *= (1.0 / std::sqrt(tot)) : p;
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
double UVector3::Normalize()
|
||||
{
|
||||
// Normalize to unit. Return normalization factor.
|
||||
double mag = Mag2();
|
||||
if (mag == 0.0) return mag;;
|
||||
mag = std::sqrt(mag);
|
||||
x /= mag;
|
||||
y /= mag;
|
||||
z /= mag;
|
||||
return mag;
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
void UVector3::RotateX(double angle)
|
||||
{
|
||||
//rotate vector around X
|
||||
double s = std::sin(angle);
|
||||
double c = std::cos(angle);
|
||||
double yy = y;
|
||||
y = c * yy - s * z;
|
||||
z = s * yy + c * z;
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
void UVector3::RotateY(double angle)
|
||||
{
|
||||
//rotate vector around Y
|
||||
double s = std::sin(angle);
|
||||
double c = std::cos(angle);
|
||||
double zz = z;
|
||||
z = c * zz - s * x;
|
||||
x = s * zz + c * x;
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
void UVector3::RotateZ(double angle)
|
||||
{
|
||||
//rotate vector around Z
|
||||
double s = std::sin(angle);
|
||||
double c = std::cos(angle);
|
||||
double xx = x;
|
||||
x = c * xx - s * y;
|
||||
y = s * xx + c * y;
|
||||
}
|
||||
|
||||
UVector3 operator + (const UVector3& a, const UVector3& b)
|
||||
{
|
||||
return UVector3(a.x + b.x, a.y + b.y, a.z + b.z);
|
||||
}
|
||||
|
||||
UVector3 operator - (const UVector3& a, const UVector3& b)
|
||||
{
|
||||
return UVector3(a.x - b.x, a.y - b.y, a.z - b.z);
|
||||
}
|
||||
|
||||
UVector3 operator * (const UVector3& p, double a)
|
||||
{
|
||||
return UVector3(a * p.x, a * p.y, a * p.z);
|
||||
}
|
||||
|
||||
UVector3 operator / (const UVector3& p, double a)
|
||||
{
|
||||
a = 1. / a;
|
||||
return UVector3(a * p.x, a * p.y, a * p.z);
|
||||
}
|
||||
|
||||
UVector3 operator * (double a, const UVector3& p)
|
||||
{
|
||||
return UVector3(a * p.x, a * p.y, a * p.z);
|
||||
}
|
||||
|
||||
double operator * (const UVector3& a, const UVector3& b)
|
||||
{
|
||||
return a.Dot(b);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,109 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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 and of QinetiQ Ltd, *
|
||||
// * subject to DEFCON 705 IPR conditions. *
|
||||
// * 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: VUFacet.cc,v 1.11 2010-09-23 10:30:07 gcosmo Exp $
|
||||
// GEANT4 tag $Name: not supported by cvs2svn $
|
||||
//
|
||||
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
//
|
||||
//
|
||||
// Author: Marek Gayer, started from original implementation by P R Truscott, 2004
|
||||
//
|
||||
|
||||
#include "VUFacet.hh"
|
||||
#include "VUSolid.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
bool VUFacet::operator== (const VUFacet &right) const
|
||||
{
|
||||
double tolerance = kCarTolerance*kCarTolerance/4.0;
|
||||
|
||||
if (GetNumberOfVertices() != right.GetNumberOfVertices())
|
||||
return false;
|
||||
else if ((GetCircumcentre()-right.GetCircumcentre()).Mag2() > tolerance)
|
||||
return false;
|
||||
else if (std::fabs((right.GetSurfaceNormal()).Dot(GetSurfaceNormal())) < 0.9999999999)
|
||||
return false;
|
||||
|
||||
bool coincident = true;
|
||||
int i = 0;
|
||||
do
|
||||
{
|
||||
coincident = false;
|
||||
int j = 0;
|
||||
do
|
||||
{
|
||||
coincident = (GetVertex(i)-right.GetVertex(j)).Mag2() < tolerance;
|
||||
} while (!coincident && ++j < GetNumberOfVertices());
|
||||
} while (coincident && ++i < GetNumberOfVertices());
|
||||
|
||||
return coincident;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void VUFacet::ApplyTranslation(const UVector3 v)
|
||||
{
|
||||
int n = GetNumberOfVertices();
|
||||
for (int i = 0; i < n; ++i)
|
||||
SetVertex(i, GetVertex(i) + v);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
std::ostream &VUFacet::StreamInfo(std::ostream &os) const
|
||||
{
|
||||
os << endl;
|
||||
os << "*********************************************************************" << endl;
|
||||
os << "FACET TYPE = " << GetEntityType() << endl;
|
||||
os << "ABSOLUTE VECTORS = " << endl;
|
||||
int n = GetNumberOfVertices();
|
||||
for (int i = 0; i < n; ++i)
|
||||
os << "P[" << i << "] = " << GetVertex(i) << endl;
|
||||
|
||||
/*
|
||||
os << "RELATIVE VECTORS = " << endl;
|
||||
for (vector<UVector3>::const_iterator it=E.begin(); it!=E.end(); it++)
|
||||
{ os << "E[" << it-E.begin()+1 << "] = " << *it << endl; }
|
||||
*/
|
||||
|
||||
os << "*********************************************************************" << endl;
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
bool VUFacet::IsInside (const UVector3 &p) const
|
||||
{
|
||||
UVector3 d = p - GetVertex(0);
|
||||
double displacement = d.Dot(GetSurfaceNormal());
|
||||
return displacement <= 0.0;
|
||||
}
|
||||
|
||||
const double VUFacet::dirTolerance = 1.0E-14;
|
||||
const double VUFacet::kCarTolerance = VUSolid::Tolerance();
|
||||
// G4GeometryTolerance::GetInstance()->GetSurfaceTolerance();
|
||||
@@ -0,0 +1,347 @@
|
||||
|
||||
#include "VUSolid.hh"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// "Universal" Solid Interface
|
||||
// Authors: J. Apostolakis, G. Cosmo, M. Gayer, A. Gheata, A. Munnich, T. Nikitina (CERN)
|
||||
//
|
||||
// Created: 25 May 2011
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
double VUSolid::fgTolerance = 1.0E-9; // cartesian tolerance; to be changed (for U was 1e-8, but we keep Geant4)
|
||||
double VUSolid::frTolerance = 1.0E-9; // radial tolerance; to be changed
|
||||
|
||||
double VUSolid::faTolerance = 1.0E-9; // angular tolerance; to be changed
|
||||
|
||||
//______________________________________________________________________________
|
||||
VUSolid::VUSolid() : fName()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
VUSolid::VUSolid(const std::string &name) :
|
||||
fName(name)
|
||||
{
|
||||
// Named constructor
|
||||
SetName(name);
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
VUSolid::~VUSolid()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
int UIntersectingCone::LineHitsCone2( const UVector3 &p,
|
||||
const UVector3 &v,
|
||||
double &s1, double &s2 )
|
||||
{
|
||||
double x0 = p.x, y0 = p.y, z0 = p.z;
|
||||
double tx = v.x, ty = v.y, tz = v.z;
|
||||
|
||||
// Special case which might not be so rare: B = 0 (precisely)
|
||||
//
|
||||
if (B==0)
|
||||
{
|
||||
if (std::fabs(tz) < 1/UUtils::kInfinity) { return 0; }
|
||||
|
||||
s1 = (A-z0)/tz;
|
||||
return 1;
|
||||
}
|
||||
|
||||
double B2 = B*B;
|
||||
|
||||
double a = tz*tz - B2*(tx*tx + ty*ty);
|
||||
double b = 2*( (z0-A)*tz - B2*(x0*tx + y0*ty) );
|
||||
double c = UUtils::sqr(z0-A) - B2*( x0*x0 + y0*y0 );
|
||||
|
||||
double radical = b*b - 4*a*c;
|
||||
|
||||
if (radical < -1E-6*std::fabs(b)) { return 0; } // No solution
|
||||
|
||||
if (radical < 1E-6*std::fabs(b))
|
||||
{
|
||||
//
|
||||
// The radical is roughly zero: check for special, very rare, cases
|
||||
//
|
||||
if (std::fabs(a) > 1/UUtils::kInfinity)
|
||||
{
|
||||
if ( std::fabs(x0*ty - y0*tx) < std::fabs(1E-6/B) )
|
||||
{
|
||||
s1 = -0.5*b/a;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
radical = std::sqrt(radical);
|
||||
}
|
||||
|
||||
if (a < -1/UUtils::kInfinity)
|
||||
{
|
||||
double sa, sb, q = -0.5*( b + (b < 0 ? -radical : +radical) );
|
||||
sa = q/a;
|
||||
sb = c/q;
|
||||
if (sa < sb) { s1 = sa; s2 = sb; } else { s1 = sb; s2 = sa; }
|
||||
if ((z0 + (s1)*tz - A)/B < 0) { return 0; }
|
||||
return 2;
|
||||
}
|
||||
else if (a > 1/UUtils::kInfinity)
|
||||
{
|
||||
double sa, sb, q = -0.5*( b + (b < 0 ? -radical : +radical) );
|
||||
sa = q/a;
|
||||
sb = c/q;
|
||||
s1 = (tz*B > 0)^(sa > sb) ? sb : sa;
|
||||
return 1;
|
||||
}
|
||||
else if (std::fabs(b) < 1/UUtils::kInfinity)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
s1 = -c/b;
|
||||
if ((z0 + (s1)*tz - A)/B < 0) { return 0; }
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
int UIntersectingCone::LineHitsCone2( const UVector3 &p,
|
||||
const UVector3 &v,
|
||||
double &s1, double &s2 )
|
||||
{
|
||||
double x0 = p.x, y0 = p.y, z0 = p.z;
|
||||
double tx = v.x, ty = v.y, tz = v.z;
|
||||
|
||||
// Special case which might not be so rare: B = 0 (precisely)
|
||||
//
|
||||
if (B==0)
|
||||
{
|
||||
if (std::fabs(tz) < 1/UUtils::kInfinity) { return 0; }
|
||||
|
||||
s1 = (A-z0)/tz;
|
||||
return 1;
|
||||
}
|
||||
|
||||
double B2 = B*B;
|
||||
|
||||
double a = tz*tz - B2*(tx*tx + ty*ty);
|
||||
double b = 2*( (z0-A)*tz - B2*(x0*tx + y0*ty) );
|
||||
double c = UUtils::sqr(z0-A) - B2*( x0*x0 + y0*y0 );
|
||||
|
||||
double radical = b*b - 4*a*c;
|
||||
|
||||
if (radical < -1E-6*std::fabs(b)) { return 0; } // No solution
|
||||
|
||||
if (radical < 1E-6*std::fabs(b))
|
||||
{
|
||||
//
|
||||
// The radical is roughly zero: check for special, very rare, cases
|
||||
//
|
||||
if (std::fabs(a) > 1/UUtils::kInfinity)
|
||||
{
|
||||
if ( std::fabs(x0*ty - y0*tx) < std::fabs(1E-6/B) )
|
||||
{
|
||||
s1 = -0.5*b/a;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
radical = std::sqrt(radical);
|
||||
}
|
||||
|
||||
if (a < -1/UUtils::kInfinity)
|
||||
{
|
||||
double sa, sb, q = -0.5*( b + (b < 0 ? -radical : +radical) );
|
||||
sa = q/a;
|
||||
sb = c/q;
|
||||
if (sa < sb) { s1 = sa; s2 = sb; } else { s1 = sb; s2 = sa; }
|
||||
if ((z0 + (s1)*tz - A)/B < 0) { return 0; }
|
||||
return 2;
|
||||
}
|
||||
else if (a > 1/UUtils::kInfinity)
|
||||
{
|
||||
double sa, sb, q = -0.5*( b + (b < 0 ? -radical : +radical) );
|
||||
sa = q/a;
|
||||
sb = c/q;
|
||||
s1 = (tz*B > 0)^(sa > sb) ? sb : sa;
|
||||
return 1;
|
||||
}
|
||||
else if (std::fabs(b) < 1/UUtils::kInfinity)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
s1 = -c/b;
|
||||
if ((z0 + (s1)*tz - A)/B < 0) { return 0; }
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Returns an estimation of the solid volume in internal units.
|
||||
// The number of statistics and error accuracy is fixed.
|
||||
// This method may be overloaded by derived classes to compute the
|
||||
// exact geometrical quantity for solids where this is possible.
|
||||
// or anyway to cache the computed value.
|
||||
// This implementation does NOT cache the computed value.
|
||||
|
||||
double VUSolid::Capacity()
|
||||
{
|
||||
int cubVolStatistics = 1000000;
|
||||
double cubVolEpsilon = 0.001;
|
||||
return EstimateCubicVolume(cubVolStatistics, cubVolEpsilon);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Calculate cubic volume based on Inside() method.
|
||||
// Accuracy is limited by the second argument or the statistics
|
||||
// expressed by the first argument.
|
||||
// Implementation is courtesy of Vasiliki Despoina Mitsou,
|
||||
// University of Athens.
|
||||
|
||||
double VUSolid::EstimateCubicVolume(int nStat, double epsilon) const
|
||||
{
|
||||
int iInside=0;
|
||||
double px,py,pz,volume;
|
||||
UVector3 min,max;
|
||||
UVector3 p;
|
||||
VUSolid::EnumInside in;
|
||||
|
||||
// values needed for CalculateExtent signature
|
||||
|
||||
// min max extents of pSolid along X,Y,Z
|
||||
|
||||
this->Extent(min,max);
|
||||
|
||||
// limits
|
||||
|
||||
if(nStat < 100) nStat = 100;
|
||||
if(epsilon > 0.01) epsilon = 0.01;
|
||||
|
||||
for(int i = 0; i < nStat; i++ )
|
||||
{
|
||||
px = min.x+(max.x-min.x)*UUtils::Random();
|
||||
py = min.y+(max.y-min.y)*UUtils::Random();
|
||||
pz = min.z+(max.z-min.z)*UUtils::Random();
|
||||
p = UVector3(px,py,pz);
|
||||
in = this->Inside(p);
|
||||
if(in != eOutside) iInside++;
|
||||
}
|
||||
volume = (max.x-min.x)*(max.y-min.y)*(max.z-min.z)*iInside/nStat;
|
||||
return volume;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Returns an estimation of the solid surface area in internal units.
|
||||
// The number of statistics and error accuracy is fixed.
|
||||
// This method may be overloaded by derived classes to compute the
|
||||
// exact geometrical quantity for solids where this is possible.
|
||||
// or anyway to cache the computed value.
|
||||
// This implementation does NOT cache the computed value.
|
||||
|
||||
double VUSolid::SurfaceArea()
|
||||
{
|
||||
int stat = 1000000;
|
||||
double ell = -1.;
|
||||
return EstimateSurfaceArea(stat,ell);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Estimate surface area based on Inside(), DistanceToIn(), and
|
||||
// DistanceToOut() methods. Accuracy is limited by the statistics
|
||||
// defined by the first argument. Implemented by Mikhail Kosov.
|
||||
|
||||
double VUSolid::EstimateSurfaceArea(int nStat, double ell) const
|
||||
{
|
||||
int inside=0;
|
||||
double px,py,pz,surf;
|
||||
UVector3 min,max;
|
||||
UVector3 p;
|
||||
VUSolid::EnumInside in;
|
||||
|
||||
// values needed for CalculateExtent signature
|
||||
|
||||
// min max extents of pSolid along X,Y,Z
|
||||
|
||||
this->Extent(min,max);
|
||||
|
||||
// limits
|
||||
|
||||
if(nStat < 100) { nStat = 100; }
|
||||
|
||||
double dX=max.x-min.x;
|
||||
double dY=max.y-min.y;
|
||||
double dZ=max.z-min.z;
|
||||
if(ell<=0.) // Automatic definition of skin thickness
|
||||
{
|
||||
double minval=dX;
|
||||
if(dY<dX) { minval=dY; }
|
||||
if(dZ<minval) { minval=dZ; }
|
||||
ell=.01*minval;
|
||||
}
|
||||
|
||||
double dd=2*ell;
|
||||
min.x-=ell; min.y-=ell; min.z-=ell; dX+=dd; dY+=dd; dZ+=dd;
|
||||
|
||||
for(int i = 0; i < nStat; i++ )
|
||||
{
|
||||
px = min.x+dX*UUtils::Random();
|
||||
py = min.y+dY*UUtils::Random();
|
||||
pz = min.z+dZ*UUtils::Random();
|
||||
p = UVector3(px,py,pz);
|
||||
in = this->Inside(p);
|
||||
if(in != eOutside)
|
||||
{
|
||||
if (SafetyFromInside(p)<ell) { inside++; }
|
||||
}
|
||||
else if(SafetyFromOutside(p)<ell) { inside++; }
|
||||
}
|
||||
// @@ The conformal correction can be upgraded
|
||||
surf = dX*dY*dZ*inside/dd/nStat;
|
||||
return surf;
|
||||
}
|
||||
|
||||
void VUSolid::ExtentAxis(EAxisType aAxis, double &aMin, double &aMax) const
|
||||
// Returns the minimum and maximum extent along the specified Cartesian axis
|
||||
{
|
||||
// Returns extent of the solid along a given cartesian axis
|
||||
if (aAxis >= 0 && aAxis <= 2)
|
||||
{
|
||||
UVector3 min, max;
|
||||
Extent(min,max);
|
||||
aMin = min[aAxis]; aMax = max[aAxis];
|
||||
}
|
||||
#ifdef USPECSDEBUG
|
||||
else
|
||||
cout << "Extent: unknown axis" << aAxis << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
void VUSolid::SetCarTolerance(double eps)
|
||||
{
|
||||
fgTolerance=eps;
|
||||
}
|
||||
void VUSolid::SetRadTolerance(double eps)
|
||||
{
|
||||
frTolerance=eps;
|
||||
}
|
||||
void VUSolid::SetAngTolerance(double eps)
|
||||
{
|
||||
faTolerance=eps;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user