source: trunk/source/geometry/solids/BREPS/src/G4FPlane.cc @ 1202

Last change on this file since 1202 was 1058, checked in by garnier, 15 years ago

file release beta

File size: 10.4 KB
Line 
1//
2// ********************************************************************
3// * License and Disclaimer                                           *
4// *                                                                  *
5// * The  Geant4 software  is  copyright of the Copyright Holders  of *
6// * the Geant4 Collaboration.  It is provided  under  the terms  and *
7// * conditions of the Geant4 Software License,  included in the file *
8// * LICENSE and available at  http://cern.ch/geant4/license .  These *
9// * include a list of copyright holders.                             *
10// *                                                                  *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work  make  any representation or  warranty, express or implied, *
14// * regarding  this  software system or assume any liability for its *
15// * use.  Please see the license in the file  LICENSE  and URL above *
16// * for the full disclaimer and the limitation of liability.         *
17// *                                                                  *
18// * This  code  implementation is the result of  the  scientific and *
19// * technical work of the GEANT4 collaboration.                      *
20// * By using,  copying,  modifying or  distributing the software (or *
21// * any work based  on the software)  you  agree  to acknowledge its *
22// * use  in  resulting  scientific  publications,  and indicate your *
23// * acceptance of all terms of the Geant4 Software license.          *
24// ********************************************************************
25//
26//
27// $Id: G4FPlane.cc,v 1.16 2006/06/29 18:42:16 gunter Exp $
28// GEANT4 tag $Name: geant4-09-02-ref-02 $
29//
30// ----------------------------------------------------------------------
31// GEANT 4 class source file
32//
33// G4FPlane.cc
34//
35// ----------------------------------------------------------------------
36// Corrections by S.Giani:
37// - The constructor using iVec now properly stores both the internal and
38//   external boundaries in the bounds vector.
39// - Proper initialization of sameSense in both the constructors.
40// - Addition of third argument (sense) in the second constructor to ensure
41//   consistent setting of the normal in all the client code.
42// - Proper use of the tolerance in the Intersect function.
43// ----------------------------------------------------------------------
44
45#include "G4FPlane.hh"
46#include "G4CompositeCurve.hh"
47
48
49G4FPlane::G4FPlane( const G4Vector3D& direction,
50                    const G4Vector3D& axis     , 
51                    const G4Point3D&  Pt0, G4int sense )
52  : pplace(direction, axis, Pt0)
53{
54  G4Point3D Pt1 = G4Point3D( Pt0 + direction );
55
56  // The plane include direction and axis is the normal,
57  // so axis^direction is included in the plane
58  G4Point3D Pt2 = G4Point3D( Pt0 + axis.cross(direction) );
59
60  G4Ray::CalcPlane3Pts( Pl, Pt0, Pt1, Pt2 );
61
62  active   = 1;
63  sameSense = sense;
64  CalcNormal();
65  distance = kInfinity;
66  Type     = 1;
67}
68
69
70G4FPlane::G4FPlane(const G4Point3DVector* pVec,
71                   const G4Point3DVector* iVec,
72                   G4int sense)
73  : pplace( (*pVec)[0]-(*pVec)[1],                    // direction
74            ((*pVec)[pVec->size()-1]-(*pVec)[0])
75            .cross((*pVec)[0]-(*pVec)[1]),            // axis
76            (*pVec)[0]                             )  // location
77
78{
79  G4Ray::CalcPlane3Pts( Pl, (*pVec)[0], (*pVec)[1], (*pVec)[2] );
80 
81  G4CurveVector bounds;
82  G4CompositeCurve* polygon;
83
84  projectedBoundary = new G4SurfaceBoundary;
85
86  sameSense = sense;
87
88  // Outer boundary
89
90  polygon= new G4CompositeCurve(*pVec);
91 
92  for (size_t i=0; i< polygon->GetSegments().size(); i++) 
93    polygon->GetSegments()[i]->SetSameSense(sameSense);
94
95  bounds.push_back(polygon);
96 
97  // Eventual inner boundary
98 
99  if (iVec) 
100  {
101    polygon= new G4CompositeCurve(*iVec);
102
103    for (size_t i=0; i< polygon->GetSegments().size(); i++) 
104    polygon->GetSegments()[i]->SetSameSense(sameSense);
105
106    bounds.push_back(polygon);
107  }
108 
109  // Set sense for boundaries 
110 
111  for (size_t j=0; j< bounds.size(); j++) 
112    bounds[j]->SetSameSense(sameSense);
113 
114
115  SetBoundaries(&bounds);
116     
117  CalcNormal();
118  IsConvex();
119  distance = kInfinity;
120  Type=1;
121}
122
123
124G4FPlane::~G4FPlane()
125{
126  delete NormalX;
127}
128
129
130void G4FPlane::CalcBBox()
131{
132  // This is needed since the bounds are used for the Solid
133  // bbox calculation. The bbox test is NOT performed for
134  // planar surfaces.
135
136  // Finds the bounds of the G4Plane surface iow
137  // calculates the bounds for a bounding box
138  // to the surface. The bounding box is used
139  // for a preliminary check of intersection.
140 
141  bbox= new G4BoundingBox3D(surfaceBoundary.BBox().GetBoxMin(), 
142                            surfaceBoundary.BBox().GetBoxMax());
143
144}
145
146
147void G4FPlane::CalcNormal()
148{
149/*
150  // Calc Normal for surface which is used for the projection
151  // Make planes
152  G4Vector3D norm;
153
154  G4Vector3D RefDirection = pplace.GetRefDirection();
155  G4Vector3D Axis = pplace.GetAxis();
156
157  // L. Broglia : before in G4Placement
158  if( RefDirection == Axis )
159    norm = RefDirection;
160  else
161  {
162    // L. Broglia : error on setY, and it`s better to use cross function
163    // norm.setX( RefDirection.y() * Axis.z() -  RefDirection.z() * Axis.y() );
164    // norm.setY( RefDirection.x() * Axis.z() -  RefDirection.z() * Axis.x() );
165    // norm.setZ( RefDirection.x() * Axis.y() -  RefDirection.y() * Axis.x() );
166       
167    norm = RefDirection.cross(Axis);
168  }
169 
170  //  const G4Point3D& tmp = pplace.GetSrfPoint();
171  const G4Point3D tmp = pplace.GetLocation();
172*/ 
173
174  // L. Broglia
175  // The direction of the normal is the axis of his location
176  // Its sense depend on the orientation of the bounded curve
177  const G4Point3D tmp = pplace.GetLocation();
178  G4Vector3D norm;
179  G4int sense = GetSameSense();
180 
181  if (sense)
182    norm = pplace.GetAxis();
183  else
184    norm = - pplace.GetAxis();
185
186  NormalX =  new G4Ray(tmp, norm);
187  NormalX->RayCheck();
188  NormalX->CreatePlanes();
189}
190
191
192void G4FPlane::Project()
193{
194    // Project
195    // const G4Plane& Plane1 = NormalX->GetPlane(1);
196    // const G4Plane& Plane2 = NormalX->GetPlane(2);
197
198    // probably not necessary
199    // projections of the boundary should be handled by the intersection
200    //    OuterBoundary->ProjectBoundaryTo2D(Plane1, Plane2, 0);
201}
202
203
204G4int G4FPlane::IsConvex() const
205{
206  return -1; 
207}
208
209
210G4int G4FPlane::Intersect(const G4Ray& rayref)
211{
212  // This function count the number of intersections of a
213  // bounded surface by a ray.
214 
215
216  // Find the intersection with the infinite plane
217  Intersected =1;
218
219  // s is solution, line is p + tq, n is G4Plane Normal, r is point on G4Plane
220  // all parameters are pointers to arrays of three elements
221 
222  hitpoint = PINFINITY;
223  register G4double a, b, t;
224
225  register const G4Vector3D& RayDir   = rayref.GetDir();
226  register const G4Point3D&  RayStart = rayref.GetStart();
227
228  G4double dirx =  RayDir.x();
229  G4double diry =  RayDir.y();
230  G4double dirz =  RayDir.z();
231
232  G4Vector3D norm = (*NormalX).GetDir();
233  G4Point3D  srf_point = pplace.GetLocation();
234
235  b = norm.x() * dirx + norm.y() * diry + norm.z() * dirz;
236
237  if ( std::fabs(b) < perMillion )   
238  {
239    // G4cout << "\nLine is parallel to G4Plane.No Hit.";
240  } 
241  else
242  {
243    G4double startx =  RayStart.x();
244    G4double starty =  RayStart.y();
245    G4double startz =  RayStart.z();   
246   
247    a = norm.x() * (srf_point.x() - startx) + 
248        norm.y() * (srf_point.y() - starty) + 
249        norm.z() * (srf_point.z() - startz)   ;
250   
251    t = a/b;
252   
253    // substitute t into line equation
254    // to calculate final solution     
255    G4double solx,soly,solz;
256    solx = startx + t * dirx;
257    soly = starty + t * diry;
258    solz = startz + t * dirz;
259
260    // solve tolerance problem
261    if( (t*dirx >= -kCarTolerance/2) && (t*dirx <= kCarTolerance/2) )
262      solx = startx;
263
264    if( (t*diry >= -kCarTolerance/2) && (t*diry <= kCarTolerance/2) )
265      soly = starty;
266
267    if( (t*dirz >= -kCarTolerance/2) && (t*dirz <= kCarTolerance/2) )
268      solz = startz;
269   
270    G4bool xhit = (dirx < 0 && solx <= startx) || (dirx >= 0 && solx >= startx);
271    G4bool yhit = (diry < 0 && soly <= starty) || (diry >= 0 && soly >= starty);
272    G4bool zhit = (dirz < 0 && solz <= startz) || (dirz >= 0 && solz >= startz);
273   
274    if( xhit && yhit && zhit ) {
275      hitpoint= G4Point3D(solx, soly, solz);
276    }
277  }
278   
279  // closest_hit is a public Point3D in G4Surface
280  closest_hit = hitpoint;
281 
282  if(closest_hit.x() == kInfinity)
283  {
284    // no hit
285    active=0;
286    SetDistance(kInfinity);
287    return 0;
288  }
289  else
290  {
291    // calculate the squared distance from the point to the intersection
292    // and set it in the distance data member (all clients know they have
293    // to take the sqrt)
294    SetDistance( RayStart.distance2(closest_hit) );   
295
296    // now, we have to verify that the hit point founded
297    // is included into the G4FPlane boundaries
298
299    // project the hit to the xy plane,
300    // with the same projection that took the boundary
301    // into projectedBoundary
302    G4Point3D projectedHit= pplace.GetToPlacementCoordinates() * closest_hit;
303   
304    // test ray from the hit on the xy plane
305    G4Ray testRay( projectedHit, G4Vector3D(1, 0.01, 0) );
306
307    // check if it intersects the boundary
308    G4int nbinter = projectedBoundary->IntersectRay2D(testRay);
309
310    // If this number is par, it`s signify that the projected point 
311    // is outside the projected surface, so the hit point is outside
312    // the bounded surface
313    if(nbinter&1)
314    {
315      // the intersection point is into the boundaries
316      // check if the intersection point is on the surface
317      if(distance <= kCarTolerance*0.5*kCarTolerance*0.5)
318      {
319        // the point is on the surface, set the distance to 0           
320        SetDistance(0);         
321      }
322      else
323      {
324        // the point is outside the surface
325      }
326     
327      return 1 ;     
328    }
329    else
330    {
331      // the intersection point is out the boundaries
332      // it is not a real intersection
333      active=0;
334      SetDistance(kInfinity);
335      return 0;
336    }
337  }
338}
339
340
341G4double G4FPlane::ClosestDistanceToPoint(const G4Point3D& Pt)
342{
343  // Calculates signed distance of point Pt to G4Plane Pl
344  // Be careful, the equation of the plane is :
345  // ax + by + cz = d
346  G4double dist = Pt.x()*Pl.a + Pt.y()*Pl.b + Pt.z()*Pl.c - Pl.d;
347
348  return dist;
349}
350
351
352void G4FPlane::InitBounded()
353{
354  // L. Broglia
355
356  projectedBoundary =
357    surfaceBoundary.Project( pplace.GetToPlacementCoordinates() );
358}
359
360G4double G4FPlane::HowNear( const G4Vector3D& Pt ) const
361{
362  G4double hownear = Pt.x()*Pl.a + Pt.y()*Pl.b + Pt.z()*Pl.c - Pl.d;
363
364  return hownear;
365}
Note: See TracBrowser for help on using the repository browser.