// @(#)root/geom:$Name: $:$Id: TGeoShape.cxx,v 1.8 2003/02/07 13:46:47 brun Exp $
// Author: Andrei Gheata 31/01/02
/*************************************************************************
* Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/
////////////////////////////////////////////////////////////////////////////////
// TGeoShape - base class for all geometrical shapes. Abstract functionality
// regarding point and segment classification has to be implemented by classes
// that inherits from it.
//
//
//
/*
*/
//
#include "TObjArray.h"
#include "TGeoMatrix.h"
#include "TGeoManager.h"
#include "TGeoVolume.h"
#include "TGeoShape.h"
#include "TVirtualGeoPainter.h"
/*************************************************************************
* TGeoShape - package description
*
* Creating shapes
*================
* Shape objects embeed only the minimum set of parameters that are fully
* describing a valid physical shape. For instance, a tube is represented by
* its half length, the minimum radius and the maximum radius. Shapes are used
* togather with media in order to create volumes, which in their turn
* are the main components of the geometrical tree. Volumes may contain other
* positioned volumes inside, which are called nodes. Each component in this
* structure : media, shapes and volumes (except nodes) are replicable (one
* instance of an object can be used in several other combinations).
* It is highly recomendable to use replicas as more as possible when volumes
* have different media but the same shape. One will never have to create
* an instance of the TGeoShape class, but only the one for specific shapes :
*
* TGeoBBox *box = new TGeoBBox(halfX, halfY, halfZ);
* TGeoTube *tub = new TGeoTube(rmin, rmax, halfZ);
* ... (see each specific shape constructors)
*
* Sometimes it is much easier to create a volume having a given shape in one
* step, since shapes are not direcly linked in the geometrical tree but volumes
* are :
*
* TGeoVolume *vol_box = gGeoManager->MakeBox("BOX_VOL", "mat1", halfX, halfY, halfZ);
* TGeoVolume *vol_tub = gGeoManager->MakeTube("TUB_VOL", "mat2", rmin, rmax, halfZ);
* ... (see MakeXXX() utilities in TGeoManager class)
*
* Volumes can be assembled also from pieces :
*
* TGeoVolume *vol = new TGeoVolume(name, ptr_shape, ptr_medium);
*
* Point and segment classification
*=================================
* The main functionalities of a shape is finding if a given point is contained
* or not or if an oriented segment crosses or not the shape. Further functionalities
* are : computing the normal to the shape surface at intersection point and finding
* the minimim distance from a point to it.
* These algorithms can be called by user only if the checked point/segment is
* converted to the local reference frame. Mainly they are used by the global
* point/segment classification algorithms of TGeoManager class.
* See also : TGeoManager::FindNode() , TGeoManager::FindNextBoundary()
*
* Classification of arbitrary curves (e.g. helixes) w.r.t shapes is not
* implemented yet.
*
*************************************************************************/
const Double_t TGeoShape::kRadDeg = 180./TMath::Pi();
const Double_t TGeoShape::kDegRad = TMath::Pi()/180.;
const Double_t TGeoShape::kBig = 1E30;
ClassImp(TGeoParamCurve)
ClassImp(TGeoShape)
//-----------------------------------------------------------------------------
TGeoShape::TGeoShape()
{
// Default constructor
fShapeId = 0;
if (!gGeoManager) {
gGeoManager = new TGeoManager("Geometry", "default geometry");
// gROOT->AddGeoManager(gGeoManager);
}
// fShapeId = gGeoManager->GetListOfShapes()->GetSize();
// gGeoManager->AddShape(this);
}
//-----------------------------------------------------------------------------
TGeoShape::TGeoShape(const char *name)
:TNamed(name, "")
{
// Default constructor
fShapeId = 0;
if (!gGeoManager) {
gGeoManager = new TGeoManager("Geometry", "default geometry");
// gROOT->AddGeoManager(gGeoManager);
}
fShapeId = gGeoManager->GetListOfShapes()->GetSize();
gGeoManager->AddShape(this);
}
//-----------------------------------------------------------------------------
TGeoShape::~TGeoShape()
{
// Destructor
if (gGeoManager) gGeoManager->GetListOfShapes()->Remove(this);
}
//-----------------------------------------------------------------------------
const char *TGeoShape::GetName() const
{
if (!strlen(fName)) {
return ((TObject *)this)->ClassName();
}
return TNamed::GetName();
}
//-----------------------------------------------------------------------------
Int_t TGeoShape::ShapeDistancetoPrimitive(Int_t numpoints, Int_t px, Int_t py) const
{
TVirtualGeoPainter *painter = gGeoManager->GetGeomPainter();
if (!painter) return 9999;
return painter->ShapeDistancetoPrimitive(this, numpoints, px, py);
}
//-----------------------------------------------------------------------------
Double_t TGeoShape::ClosenessToCorner(Double_t *point, Bool_t in,
Double_t *vertex, Double_t *normals, Double_t *cldir)
{
// Static method returning distance to closest point of a corner. The corner is
// defined by vertex and normals to the 3 planes (in order X, Y, Z - norm[9]).
// also return unit vector pointing to this
Double_t safe[3]; // closest distances to the 3 planes
Double_t dvert[3]; // vector from vertex to point
Int_t snorm = -1;
Double_t close = 0;
memset(&safe[0], 0, 3*sizeof(Double_t));
memset(cldir, 0, 3*sizeof(Double_t));
Int_t i, j;
for (i=0; i<3; i++)
dvert[i]=point[i]-vertex[i];
for (i=0; i<3; i++) {
for (j=0; j<3; j++)
safe[i]+=dvert[j]*normals[3*i+j];
}
// point is inside
if (in) {
snorm = TMath::LocMax(3, &safe[0]);
close = -safe[snorm];
// check if point was outside corner
if (close<0) return kBig;
memcpy(cldir, &normals[3*snorm], 3*sizeof(Double_t));
return close;
}
// point is outside
UInt_t nout=0;
for (i=0; i<3; i++) {
if (safe[i]>0) {
snorm = i;
close = safe[i];
nout++;
}
}
// check if point is actually inside the corner (no visible plane)
if (!nout) return kBig;
if (nout==1) {
// only one visible plane
memcpy(cldir, &normals[3*snorm], 3*sizeof(Double_t));
return close;
}
if (nout==2) {
// two faces visible
Double_t calf = 0;
Double_t s1=0;
Double_t s2=0;
for (j=0; j<3; j++) {
if (safe[j]>0) {
if (s1==0) s1=safe[j];
else s2=safe[j];
continue;
}
for (Int_t k=0; k<3; k++)
calf += normals[3*((j+1)%3)+k]*normals[3*((j+2)%3)+k];
}
close=TMath::Sqrt((s1*s1 + s2*s2 + 2.*s1*s2*calf)/(1. - calf*calf));
return close;
}
if (nout==3) {
// an edge or even vertex more close than any of the planes
// recompute closest distance
close=0;
for (i=0; i<3; i++) {
if (safe[i]>0) close+=dvert[i]*dvert[i];
}
close = TMath::Sqrt(close);
for (i=0; i<3; i++)
cldir[i] = dvert[i]/close;
return close;
}
return close; // never happens
}
//-----------------------------------------------------------------------------
Double_t TGeoShape::DistToCorner(Double_t *point, Double_t *dir, Bool_t in,
Double_t *vertex, Double_t *norm, Int_t &inorm)
{
// Static method to compute distance along a direction from inside/outside point to a corner.
// The corner is defined by its normals to planes n1, n2, n3, and its vertex.
// Also compute distance to closest plane belonging to corner, normal to this plane and
// normal to shape at intersection point.
// iact=0 :
// printf("checking corner : %f %f %fn", vertex[0], vertex[1], vertex[2]);
// printf("normx : %f %f %fn", norm[0], norm[1], norm[2]);
// printf("normy : %f %f %fn", norm[3], norm[4], norm[5]);
// printf("normz : %f %f %fn", norm[6], norm[7], norm[8]);
Double_t safe[3]; // closest distances to the 3 planes
Double_t dist[3]; // distances from point to each of the 3 planes along direction
Double_t dvert[3]; // vector from vertex to point
Double_t cosa[3]; // cosines of anles between direction and each normal
Double_t snxt = kBig;
inorm = -1;
memset(&safe[0], 0, 3*sizeof(Double_t));
memset(&cosa[0], 0, 3*sizeof(Double_t));
Int_t i, j;
for (i=0; i<3; i++) {
dvert[i]=point[i]-vertex[i];
dist[i] = kBig;
}
// printf("dvert : %f %f %fn", dvert[0], dvert[1], dvert[2]);
for (i=0; i<3; i++) {
for (j=0; j<3; j++) {
safe[i]+=dvert[j]*norm[3*i+j];
cosa[i]+=dir[j]*norm[3*i+j];
}
}
// point is inside
if (in) {
if (safe[0]>0) return kBig;
if (safe[1]>0) return kBig;
if (safe[2]>0) return kBig;
for (i=0; i<3; i++)
if (cosa[i]>0) dist[i]=-safe[i]/cosa[i];
inorm = TMath::LocMin(3, &dist[0]);
snxt = dist[inorm];
return snxt;
}
// point is outside
UInt_t npos=0;
UInt_t nout=0;
UInt_t npp=0;
Double_t dvirt = kBig;
snxt = 0;
for (i=0; i<3; i++) {
if (safe[i]>0) nout++;
if (cosa[i]!=0)
dist[i]=-safe[i]/cosa[i];
if (dist[i] < 0) continue;
npos++;
if (safe[i]>0) {
// crossing with visible plane
npp++;
if (snxt<dist[i]) {
// most distant intersection point is the real one
inorm = i;
snxt = dist[i];
}
} else {
// crossing with invisible plane
// compute distance to closest virtual intersection
dvirt=TMath::Min(dvirt, dist[i]);
}
}
// printf(" safe : %f %f %f nout=%in", safe[0], safe[1], safe[2], nout);
// printf(" dist : %f %f %fn", dist[0], dist[1], dist[2]);
// printf(" dist to next : %fn", snxt);
// printf(" closest virtual : %fn", dvirt);
// printf(" inorm=%i snorm=%in", inorm, snorm);
// printf(" nout=%i npos=%i npp=%in", nout, npos, npp);
// select distance to closest plane
if (!nout) {
// point is actually inside the corner (no visible plane)
inorm = -1;
return kBig;
}
if (nout==1) {
// only one face visible
if (npp!=1 || snxt>dvirt) {
inorm = -1;
return kBig;
}
return snxt;
}
if (!npos) {
// ray does not intersect any plane
inorm = -1;
return kBig;
}
if (npp!=nout) {
// ray ray does not intersect all visible faces
inorm = -1;
return kBig;
}
if (snxt>dvirt) {
// intersection with invisible plane closer than with real one -> no real intersection
// close=kBig;
inorm = -1;
return kBig;
}
return snxt;
}
//-----------------------------------------------------------------------------
Int_t TGeoShape::GetVertexNumber(Bool_t vx, Bool_t vy, Bool_t vz)
{
// get visible vertex number for : box, trd1, trd2, trap, gtra, para shapes
Int_t imin, imax;
if (!vz) {
imin = 0;
imax = 3;
} else {
imin = 4;
imax = 7;
}
if (!vx)
imax=imin+1;
else
imin = imax-1;
if(!vy) {
if (!vx) return imin;
return imax;
}
if (!vx) return imax;
return imin;
}
//-----------------------------------------------------------------------------
Double_t TGeoShape::SafetyPhi(Double_t *point, Bool_t in, Double_t c1, Double_t s1, Double_t c2, Double_t s2)
{
// Static method to compute safety w.r.t a phi corner defined by cosines/sines
// of the angles phi1, phi2.
Double_t saf1 = kBig;
Double_t saf2 = kBig;
if (point[0]*c1+point[1]*s1 >= 0) saf1 = -point[0]*s1 + point[1]*c1;
if (point[0]*c2+point[1]*s2 >= 0) saf2 = point[0]*s2 - point[1]*c2;
if (in) {
if (saf1<0) saf1=kBig;
if (saf2<0) saf2=kBig;
return TMath::Min(saf1,saf2);
}
if (saf1<0 && saf2<0) return TMath::Max(saf1,saf2);
return TMath::Min(saf1,saf2);
}
ROOT page - Class index - Top of the page
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.