// // ******************************************************************** // * 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: G4Ray.cc,v 1.12 2008/07/08 10:00:58 gcosmo Exp $ // GEANT4 tag $Name: geant4-09-03 $ // // ---------------------------------------------------------------------- // GEANT 4 class source file // // G4Ray.cc // // ---------------------------------------------------------------------- #include "G4Ray.hh" #include "G4PointRat.hh" G4Ray::G4Ray() { } G4Ray::G4Ray(const G4Point3D& start0, const G4Vector3D& dir0) { Init(start0, dir0); } G4Ray::~G4Ray() { } const G4Plane& G4Ray::GetPlane(G4int number_of_plane) const { if(number_of_plane==1) { return plane2; } else { return plane1; } } void G4Ray::CreatePlanes() { // Creates two orthogonal planes(plane1,plane2) the ray (rray) // situated in the intersection of the planes. The planes are // used to project the surface (nurb) in two dimensions. G4Vector3D RayDir = dir; G4Point3D RayOrigin = start; G4Point3D p1, p2, p3, p4; G4Vector3D dir1, dir2; G4Vector3D invdir = G4Vector3D( PINFINITY ); if(!NearZero(RayDir.x(), SQRT_SMALL_FASTF)) { invdir.setX(1.0 / RayDir.x()); } if(!NearZero(RayDir.y(), SQRT_SMALL_FASTF)) { invdir.setY(1.0 / RayDir.y()); } if(!NearZero(RayDir.z(), SQRT_SMALL_FASTF)) { invdir.setZ(1.0 / RayDir.z()); } MatVecOrtho(dir1, RayDir); Vcross( dir2, RayDir, dir1); Vmove(p1, RayOrigin); Vadd2(p2, RayOrigin, RayDir); Vadd2(p3, RayOrigin, dir1); Vadd2(p4, RayOrigin, dir2); CalcPlane3Pts( plane1, p1, p3, p2); CalcPlane3Pts( plane2, p1, p2, p4); } void G4Ray::MatVecOrtho(register G4Vector3D &out, register const G4Vector3D &in ) { register G4double f; G4int i_Which; if( NearZero(in.x(), 0.0001) && NearZero(in.y(), 0.0001) && NearZero(in.z(), 0.0001) ) { Vsetall( out, 0 ); return; } // Find component closest to zero f = std::fabs(in.x()); i_Which=0; if( std::fabs(in.y()) < f ) { f = std::fabs(in.y()); i_Which=1; } if( std::fabs(in.z()) < f ) { i_Which=2; } if(!i_Which) { f = std::sqrt((in.y())*(in.y())+(in.z())*(in.z())); // hypot(in.y(),in.z()) } else { if(i_Which==1) { f = std::sqrt((in.z())*(in.z())+(in.x())*(in.x())); // hypot(in.z(),in.x()) } else { f = std::sqrt((in.x())*(in.x())+(in.y())*(in.y())); // hypot(in.x(),in.y()) } } if( NearZero( f, SMALL ) ) { Vsetall( out, 0 ); return; } f = 1.0/f; if(!i_Which) { out.setX(0.0); out.setY(-in.z()*f); out.setZ( in.y()*f); } else { if(i_Which==1) { out.setY(0.0); out.setZ(-in.x()*f); out.setX( in.y()*f); } else { out.setZ(0.0); out.setX(-in.z()*f); out.setY( in.y()*f); } } } // CALC_PLANE_3PTS // // Find the equation of a G4Plane that contains three points. // Note that Normal vector created is expected to point out (see vmath.h), // so the vector from A to C had better be counter-clockwise // (about the point A) from the vector from A to B. // This follows the outward-pointing Normal convention, and the // right-hand rule for cross products. // /* C * |\ | \ ^ N | \ | \ | \ | \ | \ |C-A \ | \ | \ | \ | \ | \ \| \ *---------* A B -----> B-A */ // If the points are given in the order A B C (eg, *counter*-clockwise), // then the outward pointing surface Normal N = (B-A) x (C-A). // // Explicit Return - // 0 OK // -1 Failure. At least two of the points were not distinct, // or all three were colinear. // // Implicit Return - // G4Plane The G4Plane equation is stored here. G4int G4Ray::CalcPlane3Pts(G4Plane &plane1, const G4Point3D& a, const G4Point3D& b, const G4Point3D& c ) { // Creates the two orthogonal planes which are needed in projecting the // surface into 2D. G4Vector3D B_A; G4Vector3D C_A; G4Vector3D C_B; register G4double mag; Vsub2( B_A, b, a ); Vsub2( C_A, c, a ); Vsub2( C_B, c, b ); Vcross( plane1, B_A, C_A ); // Ensure unit length Normal mag = Magnitude(plane1); if( mag <= SQRT_SMALL_FASTF ) { return(-1);// FAIL } mag = 1/mag; G4Plane pl2(plane1); Vscale( plane1, pl2, mag ); // Find distance from the origin to the G4Plane plane1.d = Vdot( plane1, a ); return(0); //ok } void G4Ray::RayCheck() { // Check that the ray has a G4Vector3D... if (dir==G4Vector3D(0, 0, 0)) { G4Exception("G4Ray::RayCheck()", "InvalidInput", FatalException, "Invalid zero direction given !"); } // Make sure that the vector is unit length dir= dir.unit(); r_min = 0; r_max = 0; } void G4Ray::Vcross(G4Plane &a, const G4Vector3D &b, const G4Vector3D &c) { a.a = b.y() * c.z() - b.z() * c.y() ; a.b = b.z() * c.x() - b.x() * c.z() ; a.c = b.x() * c.y() - b.y() * c.x() ; } void G4Ray::Vcross(G4Vector3D &a, const G4Vector3D &b, const G4Vector3D &c) { a.setX(b.y() * c.z() - b.z() * c.y()) ; a.setY(b.z() * c.x() - b.x() * c.z()) ; a.setZ(b.x() * c.y() - b.y() * c.x()) ; } void G4Ray::Vmove(G4Point3D &a, const G4Point3D &b) { a.setX(b.x()); a.setY(b.y()); a.setZ(b.z()); } void G4Ray::Vadd2(G4Point3D &a, const G4Point3D &b, const G4Vector3D &c) { a.setX(b.x() + c.x()) ; a.setY(b.y() + c.y()) ; a.setZ(b.z() + c.z()) ; } void G4Ray::Vsub2(G4Vector3D &a, const G4Point3D &b, const G4Point3D &c) { a.setX(b.x() - c.x()); a.setY(b.y() - c.y()); a.setZ(b.z() - c.z()); } void G4Ray::Vscale(G4Plane& a, const G4Plane& b, G4double c) { a.a = b.a * c; a.b = b.b * c; a.c = b.c * c; } G4double G4Ray::Vdot(const G4Plane &a, const G4Point3D &b) { return (a.a * b.x() + a.b * b.y() + a.c * b.z()); } G4double G4Ray::Magsq(const G4Plane &a) { return ( a.a * a.a + a.b * a.b + a.c *a.c ); } G4double G4Ray::Magnitude(const G4Plane &a) { return (std::sqrt( Magsq( a )) ); }