<!-- ******************************************************** -->
<!--                                                          -->
<!--  [History]                                               -->
<!--    Converted to DocBook: Katsuya Amako, Aug-2006         -->
<!--    Changed by: Gabriele Cosmo, 18-Apr-2005               -->
<!--                                                          -->
<!-- ******************************************************** -->


<!-- ******************* Section (Level#2) ****************** -->
<sect2 id="sect.Geom.Reflec">
<title>
Reflecting Hierarchies of Volumes
</title>

<para>
Hierarchies of volumes based on <emphasis>CSG</emphasis> or 
<emphasis>specific</emphasis> solids can be reflected by means of the
<literal>G4ReflectionFactory</literal> class and <literal>G4ReflectedSolid</literal>,
which implements a solid that has been shifted from its original
reference frame to a new 'reflected' one. The reflection
transformation is applied as a decomposition into rotation and
translation transformations.
</para>

<para>
The factory is a singleton object which provides the following
methods:

<informalexample>
<programlisting>
   G4PhysicalVolumesPair Place(const G4Transform3D&amp;   transform3D,
                               const G4String&amp;        name,
                                     G4LogicalVolume* LV,
                                     G4LogicalVolume* motherLV,
                                     G4bool           isMany,
                                     G4int            copyNo,
                                     G4bool           surfCheck=false)
 
   G4PhysicalVolumesPair Replicate(const G4String&amp;        name,
                                         G4LogicalVolume* LV,
                                         G4LogicalVolume* motherLV,
                                         EAxis            axis,
                                         G4int            nofReplicas,
                                         G4double         width,
                                         G4double         offset=0)
                                                                                              
   G4PhysicalVolumesPair Divide(const G4String&amp;        name,
                                      G4LogicalVolume* LV,
                                      G4LogicalVolume* motherLV,
                                      EAxis            axis,
                                      G4int            nofDivisions,
                                      G4double         width,
                                      G4double         offset);
</programlisting>
</informalexample>
</para>

<para>
The method <literal>Place()</literal> used for placements, evaluates the
passed transformation. In case the transformation contains a
reflection, the factory will act as follows:

<orderedlist spacing="compact">
  <listitem><para>
    Performs the transformation decomposition.
  </para></listitem>
  <listitem><para>
    Creates a new reflected solid and logical volume, or retrieves
    them from a map if the reflected object was already created.
  </para></listitem>
  <listitem><para>
    Transforms the daughters (if any) and place them in the given mother.
  </para></listitem>
</orderedlist>
</para>

<para>
If successful, the result is a pair of physical volumes, where the
second physical volume is a placement in a reflected mother.
Optionally, it is also possible to force the overlaps check at the
time of placement, by activating the <literal>surfCheck</literal> flag.
</para>

<para>
The method <literal>Replicate()</literal> creates replicas in the given
mother. If successful, the result is a pair of physical volumes,
where the second physical volume is a replica in a reflected
mother.
</para>

<para>
The method <literal>Divide()</literal> creates divisions in the given mother.
If successful, the result is a pair of physical volumes, where the
second physical volume is a division in a reflected mother. There
exists also two more variants of this method which may specify or
not width or number of divisions.
</para>

<note>
<title>
Notes
</title>
<para>
<itemizedlist spacing="compact">
  <listitem><para>
    In order to reflect hierarchies containing divided volumes, it
    is necessary to explicitely instantiate a concrete <emphasis>division</emphasis>
    factory -before- applying the actual reflection: (i.e. -
    <literal>G4PVDivisionFactory::GetInstance();</literal>).
  </para></listitem>
  <listitem><para>
    Reflection of generic parameterised volumes is not possible yet.
  </para></listitem>
</itemizedlist>
</para>
</note>

<example id="programlist_Geom.Reflec_1">
<title>
An example of usage of the 
<literal>G4ReflectionFactory</literal> class.</title>
<programlisting>
 #include "G4ReflectionFactory.hh"
 
 // Calor placement with rotation
 
 G4double calThickness = 100*cm;
 G4double Xpos = calThickness*1.5;
 G4RotationMatrix* rotD3 = new G4RotationMatrix();
 rotD3-&gt;rotateY(10.*deg);
 
 G4VPhysicalVolume* physiCalor =
     new G4PVPlacement(rotD3,                     // rotation
                       G4ThreeVector(Xpos,0.,0.), // at (Xpos,0,0)
                       logicCalor,     // its logical volume (defined elsewhere)
                       "Calorimeter",  // its name
                       logicHall,      // its mother volume (defined elsewhere)
                       false,          // no boolean operation
                       0);             // copy number
 
 // Calor reflection with rotation
 //
 G4Translate3D translation(-Xpos, 0., 0.);
 G4Transform3D rotation = G4Rotate3D(*rotD3);
 G4ReflectX3D  reflection;
 G4Transform3D transform = translation*rotation*reflection;
 
 G4ReflectionFactory::Instance()
          -&gt;Place(transform,     // the transformation with reflection
                  "Calorimeter", // the actual name
                  logicCalor,    // the logical volume
                  logicHall,     // the mother volume
                  false,         // no boolean operation
                  1,             // copy number
                  false);        // no overlap check triggered
 
 // Replicate layers
 //
 G4ReflectionFactory::Instance()
          -&gt;Replicate("Layer",    // layer name
                      logicLayer, // layer logical volume (defined elsewhere)
                      logicCalor, // its mother
                      kXAxis,     // axis of replication
                      5,          // number of replica
                      20*cm);     // width of replica
</programlisting> 
</example>

</sect2>