CsgOps.cxx

Go to the documentation of this file.
00001 // @(#)root/gl:$Id: CsgOps.cxx 31664 2009-12-08 15:00:36Z matevz $
00002 // Author:  Timur Pocheptsov  01/04/2005
00003 /*
00004   CSGLib - Software Library for Constructive Solid Geometry
00005   Copyright (C) 2003-2004  Laurence Bourn
00006 
00007   This library is free software; you can redistribute it and/or
00008   modify it under the terms of the GNU Library General Public
00009   License as published by the Free Software Foundation; either
00010   version 2 of the License, or (at your option) any later version.
00011 
00012   This library is distributed in the hope that it will be useful,
00013   but WITHOUT ANY WARRANTY; without even the implied warranty of
00014   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015   Library General Public License for more details.
00016 
00017   You should have received a copy of the GNU Library General Public
00018   License along with this library; if not, write to the Free
00019   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00020 
00021   Please send remarks, questions and bug reports to laurencebourn@hotmail.com
00022 */
00023 
00024 /**
00025  * I've modified some very nice bounding box tree code from
00026  * Gino van der Bergen's Free Solid Library below. It's basically
00027  * the same code - but I've hacked out the transformation stuff as
00028  * I didn't understand it. I've also made it far less elegant!
00029  * Laurence Bourn.
00030  */
00031 
00032 /*
00033   SOLID - Software Library for Interference Detection
00034   Copyright (C) 1997-1998  Gino van den Bergen
00035 
00036   This library is free software; you can redistribute it and/or
00037   modify it under the terms of the GNU Library General Public
00038   License as published by the Free Software Foundation; either
00039   version 2 of the License, or (at your option) any later version.
00040 
00041   This library is distributed in the hope that it will be useful,
00042   but WITHOUT ANY WARRANTY; without even the implied warranty of
00043   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00044   Library General Public License for more details.
00045 
00046   You should have received a copy of the GNU Library General Public
00047   License along with this library; if not, write to the Free
00048   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00049 
00050   Please send remarks, questions and bug reports to gino@win.tue.nl,
00051   or write to:
00052                   Gino van den Bergen
00053          Department of Mathematics and Computing Science
00054          Eindhoven University of Technology
00055          P.O. Box 513, 5600 MB Eindhoven, The Netherlands
00056 */
00057 
00058 /*
00059    This file contains compressed version of CSGSolid and SOLID.
00060    All stuff is in RootCsg namespace,
00061    I used ROOT's own typedefs and math functions, removed resulting triangulation
00062    (I use OpenGL's inner implementation), changed names from MT_xxx CSG_xxx
00063    to more natural etc.
00064    Interface to CSGSolid :
00065    ConvertToMesh(to convert TBuffer3D to mesh)
00066    BuildUnion
00067    BuildIntersection
00068    BuildDifference
00069 
00070    31.03.05 Timur Pocheptsov.
00071 */
00072 
00073 #include <algorithm>
00074 #include <vector>
00075 
00076 #include "TBuffer3D.h"
00077 #include "Rtypes.h"
00078 #include "TMath.h"
00079 #include "CsgOps.h"
00080 
00081 namespace RootCsg {
00082 
00083    const Double_t epsilon = 1e-10;
00084    const Double_t epsilon2 = 1e-20;
00085    const Double_t infinity = 1e50;
00086 
00087    //______________________________________________________________________________
00088    Int_t sign(Double_t x)
00089    {
00090       return x < 0. ? -1 : x > 0. ? 1 : 0;
00091    }
00092 
00093    //______________________________________________________________________________
00094    Bool_t fuzzy_zero(Double_t x)
00095    {
00096       return TMath::Abs(x) < epsilon;
00097    }
00098 
00099    //______________________________________________________________________________
00100    Bool_t fuzzy_zero2(Double_t x)
00101    {
00102       return TMath::Abs(x) < epsilon2;
00103    }
00104 
00105    class Tuple2 {
00106    protected:
00107       Double_t fCo[2];
00108 
00109    public:
00110       Tuple2(){SetValue(0, 0);}
00111       Tuple2(const Double_t *vv){SetValue(vv);}
00112       Tuple2(Double_t xx, Double_t yy){SetValue(xx, yy);}
00113 
00114       Double_t       &operator [] (Int_t i){return fCo[i];}
00115       const Double_t &operator [] (Int_t i)const{return fCo[i];}
00116 
00117       Double_t       &X(){return fCo[0];}
00118       const Double_t &X()const{return fCo[0];}
00119       Double_t       &Y(){return fCo[1];}
00120       const Double_t &Y()const{return fCo[1];}
00121       Double_t       &U(){return fCo[0];}
00122       const Double_t &U()const{return fCo[0];}
00123       Double_t       &V(){return fCo[1];}
00124       const Double_t &V()const{return fCo[1];}
00125 
00126       Double_t       *GetValue(){return fCo;}
00127       const Double_t *GetValue()const{return fCo;}
00128       void            GetValue(Double_t *vv)const{vv[0] = fCo[0]; vv[1] = fCo[1];}
00129 
00130       void            SetValue(const Double_t *vv){fCo[0] = vv[0]; fCo[1] = vv[1];}
00131       void            SetValue(Double_t xx, Double_t yy){fCo[0] = xx; fCo[1] = yy;}
00132    };
00133 
00134    Bool_t operator == (const Tuple2 &t1, const Tuple2 &t2)
00135    {
00136       return t1[0] == t2[0] && t1[1] == t2[1];
00137    }
00138 
00139    class TVector2 : public Tuple2 {
00140    public:
00141       TVector2(){}
00142       TVector2(const Double_t *v) : Tuple2(v) {}
00143       TVector2(Double_t xx, Double_t yy) : Tuple2(xx, yy) {}
00144 
00145       TVector2 &operator += (const TVector2 &v);
00146       TVector2 &operator -= (const TVector2 &v);
00147       TVector2 &operator *= (Double_t s);
00148       TVector2 &operator /= (Double_t s);
00149 
00150       Double_t Dot(const TVector2 &v)const;
00151       Double_t Length2()const;
00152       Double_t Length()const;
00153       TVector2 Absolute()const;
00154       void     Normalize();
00155       TVector2 Normalized()const;
00156       void     Scale(Double_t x, Double_t y);
00157       TVector2 Scaled(Double_t x, Double_t y)const;
00158       Bool_t   FuzzyZero()const;
00159       Double_t Angle(const TVector2 &v)const;
00160       TVector2 Cross(const TVector2 &v)const;
00161       Double_t Triple(const TVector2 &v1, const TVector2 &v2)const;
00162    };
00163 
00164    //______________________________________________________________________________
00165    TVector2 &TVector2::operator+=(const TVector2 &vv)
00166    {
00167       //
00168       fCo[0] += vv[0]; fCo[1] += vv[1];
00169       return *this;
00170    }
00171 
00172    //______________________________________________________________________________
00173    TVector2 &TVector2::operator-=(const TVector2 &vv)
00174    {
00175       //
00176       fCo[0] -= vv[0]; fCo[1] -= vv[1];
00177       return *this;
00178    }
00179 
00180    //______________________________________________________________________________
00181    TVector2 &TVector2::operator *= (Double_t s)
00182    {
00183       //
00184       fCo[0] *= s; fCo[1] *= s; return *this;
00185    }
00186 
00187    //______________________________________________________________________________
00188    TVector2 &TVector2::operator /= (Double_t s)
00189    {
00190       //
00191       return *this *= 1. / s;
00192    }
00193 
00194    //______________________________________________________________________________
00195    TVector2 operator + (const TVector2 &v1, const TVector2 &v2)
00196    {
00197       //
00198       return TVector2(v1[0] + v2[0], v1[1] + v2[1]);
00199    }
00200 
00201    //______________________________________________________________________________
00202    TVector2 operator - (const TVector2 &v1, const TVector2 &v2)
00203    {
00204       //
00205       return TVector2(v1[0] - v2[0], v1[1] - v2[1]);
00206    }
00207 
00208    //______________________________________________________________________________
00209    TVector2 operator - (const TVector2 &v)
00210    {
00211       //
00212       return TVector2(-v[0], -v[1]);
00213    }
00214 
00215    //______________________________________________________________________________
00216    TVector2 operator * (const TVector2 &v, Double_t s)
00217    {
00218       //
00219       return TVector2(v[0] * s, v[1] * s);
00220    }
00221 
00222    //______________________________________________________________________________
00223    TVector2 operator * (Double_t s, const TVector2 &v)
00224    {
00225       //
00226       return v * s;
00227    }
00228 
00229    //______________________________________________________________________________
00230    TVector2 operator / (const TVector2 & v, Double_t s)
00231    {
00232       //
00233       return v * (1.0 / s);
00234    }
00235 
00236    //______________________________________________________________________________
00237    Double_t TVector2::Dot(const TVector2 &vv)const
00238    {
00239       //
00240       return fCo[0] * vv[0] + fCo[1] * vv[1];
00241    }
00242 
00243    //______________________________________________________________________________
00244    Double_t TVector2::Length2()const
00245    {
00246       //
00247       return Dot(*this);
00248    }
00249 
00250    //______________________________________________________________________________
00251    Double_t TVector2::Length()const
00252    {
00253       //
00254       return TMath::Sqrt(Length2());
00255    }
00256 
00257    //______________________________________________________________________________
00258    TVector2 TVector2::Absolute()const
00259    {
00260       //
00261       return TVector2(TMath::Abs(fCo[0]), TMath::Abs(fCo[1]));
00262    }
00263 
00264    //______________________________________________________________________________
00265    Bool_t TVector2::FuzzyZero()const
00266    {
00267       //
00268       return fuzzy_zero2(Length2());
00269    }
00270 
00271    //______________________________________________________________________________
00272    void TVector2::Normalize()
00273    {
00274       //
00275       *this /= Length();
00276    }
00277 
00278    //______________________________________________________________________________
00279    TVector2 TVector2::Normalized()const
00280    {
00281       //
00282       return *this / Length();
00283    }
00284 
00285    //______________________________________________________________________________
00286    void TVector2::Scale(Double_t xx, Double_t yy)
00287    {
00288       //
00289       fCo[0] *= xx; fCo[1] *= yy;
00290    }
00291 
00292    //______________________________________________________________________________
00293    TVector2 TVector2::Scaled(Double_t xx, Double_t yy)const
00294    {
00295       //
00296       return TVector2(fCo[0] * xx, fCo[1] * yy);
00297    }
00298 
00299    //______________________________________________________________________________
00300    Double_t TVector2::Angle(const TVector2 &vv)const
00301    {
00302       //
00303       Double_t s = TMath::Sqrt(Length2() * vv.Length2());
00304       return TMath::ACos(Dot(vv) / s);
00305    }
00306 
00307    //______________________________________________________________________________
00308    Double_t  dot(const TVector2 &v1, const TVector2 &v2)
00309    {
00310       //
00311       return v1.Dot(v2);
00312    }
00313 
00314    //______________________________________________________________________________
00315    Double_t length2(const TVector2 &v)
00316    {
00317       return v.Length2();
00318    }
00319 
00320    //______________________________________________________________________________
00321    Double_t length(const TVector2 &v)
00322    {
00323       return v.Length();
00324    }
00325 
00326    //______________________________________________________________________________
00327    Bool_t fuzzy_zero(const TVector2 &v)
00328    {
00329       return v.FuzzyZero();
00330    }
00331 
00332    //______________________________________________________________________________
00333    Bool_t fuzzy_equal(const TVector2 &v1, const TVector2 &v2)
00334    {
00335       return fuzzy_zero(v1 - v2);
00336    }
00337 
00338    //______________________________________________________________________________
00339    Double_t Angle(const TVector2 &v1, const TVector2 &v2)
00340    {
00341       return v1.Angle(v2);
00342    }
00343 
00344    class TPoint2 : public TVector2 {
00345    public:
00346       TPoint2(){}
00347       TPoint2(const Double_t *v) : TVector2(v){}
00348       TPoint2(Double_t x, Double_t y) : TVector2(x, y) {}
00349 
00350       TPoint2 &operator += (const TVector2 &v);
00351       TPoint2 &operator -= (const TVector2 &v);
00352       TPoint2 &operator = (const TVector2 &v);
00353 
00354       Double_t Distance(const TPoint2 &p)const;
00355       Double_t Distance2(const TPoint2 &p)const;
00356       TPoint2   Lerp(const TPoint2 &p, Double_t t)const;
00357    };
00358 
00359    //______________________________________________________________________________
00360    TPoint2 &TPoint2::operator += (const TVector2 &v)
00361    {
00362       //
00363       fCo[0] += v[0]; fCo[1] += v[1];
00364       return *this;
00365    }
00366 
00367    //______________________________________________________________________________
00368    TPoint2 &TPoint2::operator-=(const TVector2& v)
00369    {
00370       //
00371       fCo[0] -= v[0]; fCo[1] -= v[1];
00372       return *this;
00373    }
00374 
00375    //______________________________________________________________________________
00376    TPoint2 &TPoint2::operator=(const TVector2& v)
00377    {
00378       //
00379       fCo[0] = v[0]; fCo[1] = v[1];
00380       return *this;
00381    }
00382 
00383    //______________________________________________________________________________
00384    Double_t TPoint2::Distance(const TPoint2& p)const
00385    {
00386       //
00387       return (p - *this).Length();
00388    }
00389 
00390    //______________________________________________________________________________
00391    Double_t TPoint2::Distance2(const TPoint2& p)const
00392    {
00393       //
00394       return (p - *this).Length2();
00395    }
00396 
00397    //______________________________________________________________________________
00398    TPoint2 TPoint2::Lerp(const TPoint2 &p, Double_t t)const
00399    {
00400       //
00401       return TPoint2(fCo[0] + (p[0] - fCo[0]) * t,
00402                     fCo[1] + (p[1] - fCo[1]) * t);
00403    }
00404 
00405    //______________________________________________________________________________
00406    TPoint2 operator + (const TPoint2 &p, const TVector2 &v)
00407    {
00408       //
00409       return TPoint2(p[0] + v[0], p[1] + v[1]);
00410    }
00411 
00412    //______________________________________________________________________________
00413    TPoint2 operator - (const TPoint2 &p, const TVector2 &v)
00414    {
00415       //
00416       return TPoint2(p[0] - v[0], p[1] - v[1]);
00417    }
00418 
00419    //______________________________________________________________________________
00420    TVector2 operator - (const TPoint2 &p1, const TPoint2 &p2)
00421    {
00422       //
00423       return TVector2(p1[0] - p2[0], p1[1] - p2[1]);
00424    }
00425 
00426    //______________________________________________________________________________
00427    Double_t distance(const TPoint2 &p1, const TPoint2 &p2)
00428    {
00429       //
00430       return p1.Distance(p2);
00431    }
00432 
00433    //______________________________________________________________________________
00434    Double_t distance2(const TPoint2 &p1, const TPoint2 &p2)
00435    {
00436       //
00437       return p1.Distance2(p2);
00438    }
00439 
00440    //______________________________________________________________________________
00441    TPoint2 lerp(const TPoint2 &p1, const TPoint2 &p2, Double_t t)
00442    {
00443       //
00444       return p1.Lerp(p2, t);
00445    }
00446 
00447    class Tuple3 {
00448    protected:
00449       Double_t fCo[3];
00450    public:
00451       Tuple3(){SetValue(0, 0, 0);}
00452       Tuple3(const Double_t *v){SetValue(v);}
00453       Tuple3(Double_t xx, Double_t yy, Double_t zz){SetValue(xx, yy, zz);}
00454 
00455       Double_t       &operator [] (Int_t i){return fCo[i];}
00456       const Double_t &operator [] (Int_t i)const{return fCo[i];}
00457 
00458       Double_t       &X(){return fCo[0];}
00459       const Double_t &X()const{return fCo[0];}
00460       Double_t       &Y(){return fCo[1];}
00461       const Double_t &Y()const{return fCo[1];}
00462       Double_t       &Z(){return fCo[2];}
00463       const Double_t &Z()const{return fCo[2];}
00464 
00465       Double_t       *GetValue(){return fCo;}
00466       const Double_t *GetValue()const{ return fCo; }
00467 
00468       void GetValue(Double_t *v)const
00469       {
00470          v[0] = Double_t(fCo[0]), v[1] = Double_t(fCo[1]), v[2] = Double_t(fCo[2]);
00471       }
00472 
00473       void SetValue(const Double_t *v)
00474       {
00475          fCo[0] = Double_t(v[0]), fCo[1] = Double_t(v[1]), fCo[2] = Double_t(v[2]);
00476       }
00477       void SetValue(Double_t xx, Double_t yy, Double_t zz)
00478       {
00479          fCo[0] = xx; fCo[1] = yy; fCo[2] = zz;
00480       }
00481    };
00482 
00483    //______________________________________________________________________________
00484    Bool_t operator==(const Tuple3& t1, const Tuple3& t2)
00485    {
00486       return t1[0] == t2[0] && t1[1] == t2[1] && t1[2] == t2[2];
00487    }
00488 
00489    class TVector3 : public Tuple3 {
00490    public:
00491       TVector3(){}
00492       TVector3(const Double_t *v) : Tuple3(v){}
00493       TVector3(Double_t xx, Double_t yy, Double_t zz) : Tuple3(xx, yy, zz){}
00494 
00495       TVector3 &operator += (const TVector3& v);
00496       TVector3 &operator -= (const TVector3& v);
00497       TVector3 &operator *= (Double_t s);
00498       TVector3 &operator /= (Double_t s);
00499 
00500       Double_t Dot(const TVector3& v)const;
00501       Double_t Length2()const;
00502       Double_t Length()const;
00503       TVector3  Absolute()const;
00504       void     NoiseGate(Double_t threshold);
00505       void     Normalize();
00506       TVector3  Normalized()const;
00507       TVector3  SafeNormalized()const;
00508       void     Scale(Double_t x, Double_t y, Double_t z);
00509       TVector3  Scaled(Double_t x, Double_t y, Double_t z)const;
00510       Bool_t   FuzzyZero()const;
00511       Double_t Angle(const TVector3 &v)const;
00512       TVector3  Cross(const TVector3 &v)const;
00513       Double_t Triple(const TVector3 &v1, const TVector3 &v2)const;
00514       Int_t    ClosestAxis()const;
00515 
00516       static TVector3 Random();
00517    };
00518 
00519    //______________________________________________________________________________
00520    TVector3 &TVector3::operator += (const TVector3 &v)
00521    {
00522       //
00523       fCo[0] += v[0]; fCo[1] += v[1]; fCo[2] += v[2];
00524       return *this;
00525    }
00526 
00527    //______________________________________________________________________________
00528    TVector3 &TVector3::operator -= (const TVector3 &v)
00529    {
00530       //
00531       fCo[0] -= v[0]; fCo[1] -= v[1]; fCo[2] -= v[2];
00532       return *this;
00533    }
00534 
00535    //______________________________________________________________________________
00536    TVector3 &TVector3::operator *= (Double_t s)
00537    {
00538       //
00539       fCo[0] *= s; fCo[1] *= s; fCo[2] *= s;
00540       return *this;
00541    }
00542 
00543    //______________________________________________________________________________
00544    TVector3 &TVector3::operator /= (Double_t s)
00545    {
00546       //
00547       return *this *= Double_t(1.0) / s;
00548    }
00549 
00550    //______________________________________________________________________________
00551    Double_t TVector3::Dot(const TVector3 &v)const
00552    {
00553       //
00554       return fCo[0] * v[0] + fCo[1] * v[1] + fCo[2] * v[2];
00555    }
00556 
00557    //______________________________________________________________________________
00558    Double_t TVector3::Length2()const
00559    {
00560       //
00561       return Dot(*this);
00562    }
00563 
00564    //______________________________________________________________________________
00565    Double_t TVector3::Length()const
00566    {
00567       //
00568       return TMath::Sqrt(Length2());
00569    }
00570 
00571    //______________________________________________________________________________
00572    TVector3 TVector3::Absolute()const
00573    {
00574       //
00575       return TVector3(TMath::Abs(fCo[0]), TMath::Abs(fCo[1]), TMath::Abs(fCo[2]));
00576    }
00577 
00578    //______________________________________________________________________________
00579    Bool_t TVector3::FuzzyZero()const
00580    {
00581       //
00582       return fuzzy_zero(Length2());
00583    }
00584 
00585    //______________________________________________________________________________
00586    void TVector3::NoiseGate(Double_t threshold)
00587    {
00588       //
00589       if (Length2() < threshold) SetValue(0., 0., 0.);
00590    }
00591 
00592    //______________________________________________________________________________
00593    void TVector3::Normalize()
00594    {
00595       //
00596       *this /= Length();
00597    }
00598 
00599    //______________________________________________________________________________
00600    TVector3 operator * (const TVector3 &v, Double_t s)
00601    {
00602       return TVector3(v[0] * s, v[1] * s, v[2] * s);
00603    }
00604 
00605    //______________________________________________________________________________
00606    TVector3 operator / (const TVector3 &v, Double_t s)
00607    {
00608       return v * (1. / s);
00609    }
00610 
00611    //______________________________________________________________________________
00612    TVector3 TVector3::Normalized()const
00613    {
00614       //
00615       return *this / Length();
00616    }
00617 
00618    //______________________________________________________________________________
00619    TVector3 TVector3::SafeNormalized()const
00620    {
00621       //
00622       Double_t len = Length();
00623       return fuzzy_zero(len) ? TVector3(1., 0., 0.):*this / len;
00624    }
00625 
00626    //______________________________________________________________________________
00627    void TVector3::Scale(Double_t xx, Double_t yy, Double_t zz)
00628    {
00629       //
00630       fCo[0] *= xx; fCo[1] *= yy; fCo[2] *= zz;
00631    }
00632 
00633    //______________________________________________________________________________
00634    TVector3 TVector3::Scaled(Double_t xx, Double_t yy, Double_t zz)const
00635    {
00636       //
00637       return TVector3(fCo[0] * xx, fCo[1] * yy, fCo[2] * zz);
00638    }
00639 
00640    //______________________________________________________________________________
00641    Double_t TVector3::Angle(const TVector3 &v)const
00642    {
00643       //
00644       Double_t s = TMath::Sqrt(Length2() * v.Length2());
00645       return TMath::ACos(Dot(v) / s);
00646    }
00647 
00648    //______________________________________________________________________________
00649    TVector3 TVector3::Cross(const TVector3 &v)const
00650    {
00651       //
00652       return TVector3(fCo[1] * v[2] - fCo[2] * v[1],
00653                      fCo[2] * v[0] - fCo[0] * v[2],
00654                      fCo[0] * v[1] - fCo[1] * v[0]);
00655    }
00656 
00657    //______________________________________________________________________________
00658    Double_t TVector3::Triple(const TVector3 &v1, const TVector3 &v2)const
00659    {
00660       //
00661       return fCo[0] * (v1[1] * v2[2] - v1[2] * v2[1]) +
00662              fCo[1] * (v1[2] * v2[0] - v1[0] * v2[2]) +
00663              fCo[2] * (v1[0] * v2[1] - v1[1] * v2[0]);
00664    }
00665 
00666    //______________________________________________________________________________
00667    Int_t TVector3::ClosestAxis()const
00668    {
00669       //
00670       TVector3 a = Absolute();
00671       return a[0] < a[1] ? (a[1] < a[2] ? 2 : 1) : (a[0] < a[2] ? 2 : 0);
00672    }
00673 
00674    //______________________________________________________________________________
00675    TVector3 operator + (const TVector3 &v1, const TVector3 &v2)
00676    {
00677       return TVector3(v1[0] + v2[0], v1[1] + v2[1], v1[2] + v2[2]);
00678    }
00679 
00680    //______________________________________________________________________________
00681    TVector3 operator - (const TVector3 &v1, const TVector3 &v2)
00682    {
00683       return TVector3(v1[0] - v2[0], v1[1] - v2[1], v1[2] - v2[2]);
00684    }
00685 
00686    //______________________________________________________________________________
00687    TVector3 operator - (const TVector3 &v)
00688    {
00689       return TVector3(-v[0], -v[1], -v[2]);
00690    }
00691 
00692    //______________________________________________________________________________
00693    TVector3 operator * (Double_t s, const TVector3 &v)
00694    {
00695       return v * s;
00696    }
00697 
00698    //______________________________________________________________________________
00699    TVector3 operator * (const TVector3 &v1, const TVector3 &v2)
00700    {
00701       return TVector3(v1[0] * v2[0], v1[1] * v2[1], v1[2] * v2[2]);
00702    }
00703 
00704    //______________________________________________________________________________
00705    Double_t  dot(const TVector3 &v1, const TVector3 &v2)
00706    {
00707       return v1.Dot(v2);
00708    }
00709 
00710    //______________________________________________________________________________
00711    Double_t length2(const TVector3 &v)
00712    {
00713       return v.Length2();
00714    }
00715 
00716    //______________________________________________________________________________
00717    Double_t length(const TVector3 &v)
00718    {
00719       return v.Length();
00720    }
00721 
00722    //______________________________________________________________________________
00723    Bool_t fuzzy_zero(const TVector3 &v)
00724    {
00725       return v.FuzzyZero();
00726    }
00727 
00728    //______________________________________________________________________________
00729    Bool_t fuzzy_equal(const TVector3 &v1, const TVector3 &v2)
00730    {
00731       return fuzzy_zero(v1 - v2);
00732    }
00733 
00734    //______________________________________________________________________________
00735    Double_t Angle(const TVector3 &v1, const TVector3 &v2)
00736    {
00737       return v1.Angle(v2);
00738    }
00739 
00740    //______________________________________________________________________________
00741    TVector3 cross(const TVector3 &v1, const TVector3 &v2)
00742    {
00743       return v1.Cross(v2);
00744    }
00745 
00746    //______________________________________________________________________________
00747    Double_t triple(const TVector3 &v1, const TVector3 &v2, const TVector3 &v3)
00748    {
00749       return v1.Triple(v2, v3);
00750    }
00751 
00752    class TPoint3 : public TVector3 {
00753    public:
00754       TPoint3(){}
00755       TPoint3(const Double_t *v) : TVector3(v) {}
00756       TPoint3(Double_t xx, Double_t yy, Double_t zz) : TVector3(xx, yy, zz) {}
00757 
00758       TPoint3 &operator += (const TVector3 &v);
00759       TPoint3 &operator -= (const TVector3 &v);
00760       TPoint3 &operator = (const TVector3 &v);
00761 
00762       Double_t Distance(const TPoint3 &p)const;
00763       Double_t Distance2(const TPoint3 &p)const;
00764       TPoint3   Lerp(const TPoint3 &p, Double_t t)const;
00765    };
00766 
00767    //______________________________________________________________________________
00768    TPoint3 &TPoint3::operator += (const TVector3 &v)
00769    {
00770       //
00771       fCo[0] += v[0]; fCo[1] += v[1]; fCo[2] += v[2];
00772       return *this;
00773    }
00774 
00775    //______________________________________________________________________________
00776    TPoint3 &TPoint3::operator-=(const TVector3 &v)
00777    {
00778       //
00779       fCo[0] -= v[0]; fCo[1] -= v[1]; fCo[2] -= v[2];
00780       return *this;
00781    }
00782 
00783    //______________________________________________________________________________
00784    TPoint3 &TPoint3::operator=(const TVector3 &v)
00785    {
00786       //
00787       fCo[0] = v[0]; fCo[1] = v[1]; fCo[2] = v[2];
00788       return *this;
00789    }
00790 
00791    //______________________________________________________________________________
00792    Double_t TPoint3::Distance(const TPoint3 &p)const
00793    {
00794       //
00795       return (p - *this).Length();
00796    }
00797 
00798    //______________________________________________________________________________
00799    Double_t TPoint3::Distance2(const TPoint3 &p)const
00800    {
00801       //
00802       return (p - *this).Length2();
00803    }
00804 
00805    //______________________________________________________________________________
00806    TPoint3 TPoint3::Lerp(const TPoint3 &p, Double_t t)const
00807    {
00808       //
00809       return TPoint3(fCo[0] + (p[0] - fCo[0]) * t,
00810                     fCo[1] + (p[1] - fCo[1]) * t,
00811                     fCo[2] + (p[2] - fCo[2]) * t);
00812    }
00813 
00814    //______________________________________________________________________________
00815    TPoint3 operator + (const TPoint3 &p, const TVector3 &v)
00816    {
00817       return TPoint3(p[0] + v[0], p[1] + v[1], p[2] + v[2]);
00818    }
00819 
00820    //______________________________________________________________________________
00821    TPoint3 operator - (const TPoint3 &p, const TVector3 &v)
00822    {
00823       return TPoint3(p[0] - v[0], p[1] - v[1], p[2] - v[2]);
00824    }
00825 
00826    //______________________________________________________________________________
00827    TVector3 operator - (const TPoint3 &p1, const TPoint3 &p2)
00828    {
00829       return TVector3(p1[0] - p2[0], p1[1] - p2[1], p1[2] - p2[2]);
00830    }
00831 
00832    //______________________________________________________________________________
00833    Double_t distance(const TPoint3 &p1, const TPoint3 &p2)
00834    {
00835       return p1.Distance(p2);
00836    }
00837 
00838    //______________________________________________________________________________
00839    Double_t distance2(const TPoint3 &p1, const TPoint3 &p2)
00840    {
00841       return p1.Distance2(p2);
00842    }
00843 
00844    //______________________________________________________________________________
00845    TPoint3 lerp(const TPoint3 &p1, const TPoint3 &p2, Double_t t)
00846    {
00847       return p1.Lerp(p2, t);
00848    }
00849 
00850    class Tuple4 {
00851    protected:
00852       Double_t fCo[4];
00853 
00854    public:
00855       Tuple4(){SetValue(0, 0, 0, 0);}
00856       Tuple4(const Double_t *v){SetValue(v);}
00857       Tuple4(Double_t xx, Double_t yy, Double_t zz, Double_t ww)
00858       {
00859          SetValue(xx, yy, zz, ww);
00860       }
00861 
00862       Double_t       &operator [] (Int_t i){return fCo[i];}
00863       const Double_t &operator [] (Int_t i)const{return fCo[i];}
00864 
00865       Double_t       &X(){return fCo[0];}
00866       const Double_t &X()const{return fCo[0];}
00867       Double_t       &Y(){return fCo[1];}
00868       const Double_t &Y()const{return fCo[1];}
00869       Double_t       &Z(){return fCo[2];}
00870       const Double_t &Z()const{return fCo[2];}
00871       Double_t       &W(){return fCo[3];}
00872       const Double_t &W()const{return fCo[3];}
00873 
00874       Double_t       *GetValue(){return fCo;}
00875       const Double_t *GetValue()const{return fCo;}
00876 
00877       void GetValue(Double_t *v)const
00878       {
00879          v[0] = fCo[0]; v[1] = fCo[1]; v[2] = fCo[2]; v[3] = fCo[3];
00880       }
00881 
00882       void SetValue(const Double_t *v)
00883       {
00884          fCo[0] = v[0]; fCo[1] = v[1]; fCo[2] = v[2]; fCo[3] = v[3];
00885       }
00886       void SetValue(Double_t xx, Double_t yy, Double_t zz, Double_t ww)
00887       {
00888          fCo[0] = xx; fCo[1] = yy; fCo[2] = zz; fCo[3] = ww;
00889       }
00890    };
00891 
00892    //______________________________________________________________________________
00893    Bool_t operator == (const Tuple4 &t1, const Tuple4 &t2)
00894    {
00895       return t1[0] == t2[0] && t1[1] == t2[1] && t1[2] == t2[2] && t1[3] == t2[3];
00896    }
00897 
00898    class TMatrix3x3 {
00899    protected:
00900       TVector3 fEl[3];
00901 
00902    public:
00903       TMatrix3x3(){}
00904       TMatrix3x3(const Double_t *m){SetValue(m);}
00905       TMatrix3x3(const TVector3 &euler){SetEuler(euler);}
00906       TMatrix3x3(const TVector3 &euler, const TVector3 &s)
00907       {
00908          SetEuler(euler); Scale(s[0], s[1], s[2]);
00909       }
00910       TMatrix3x3(Double_t xx, Double_t xy, Double_t xz,
00911                 Double_t yx, Double_t yy, Double_t yz,
00912                 Double_t zx, Double_t zy, Double_t zz)
00913       {
00914          SetValue(xx, xy, xz, yx, yy, yz, zx, zy, zz);
00915       }
00916 
00917       TVector3 &operator       [] (Int_t i){return fEl[i];}
00918       const TVector3 &operator [] (Int_t i)const{return fEl[i];}
00919 
00920       void SetValue(const Double_t *m)
00921       {
00922          fEl[0][0] = *m++; fEl[1][0] = *m++; fEl[2][0] = *m++; m++;
00923          fEl[0][1] = *m++; fEl[1][1] = *m++; fEl[2][1] = *m++; m++;
00924          fEl[0][2] = *m++; fEl[1][2] = *m++; fEl[2][2] = *m;
00925       }
00926       void SetValue(Double_t xx, Double_t xy, Double_t xz,
00927                     Double_t yx, Double_t yy, Double_t yz,
00928                     Double_t zx, Double_t zy, Double_t zz)
00929       {
00930          fEl[0][0] = xx; fEl[0][1] = xy; fEl[0][2] = xz;
00931          fEl[1][0] = yx; fEl[1][1] = yy; fEl[1][2] = yz;
00932          fEl[2][0] = zx; fEl[2][1] = zy; fEl[2][2] = zz;
00933       }
00934       void SetEuler(const TVector3 &euler)
00935       {
00936          Double_t ci = TMath::Cos(euler[0]);
00937          Double_t cj = TMath::Cos(euler[1]);
00938          Double_t ch = TMath::Cos(euler[2]);
00939          Double_t si = TMath::Sin(euler[0]);
00940          Double_t sj = TMath::Sin(euler[1]);
00941          Double_t sh = TMath::Sin(euler[2]);
00942          Double_t cc = ci * ch;
00943          Double_t cs = ci * sh;
00944          Double_t sc = si * ch;
00945          Double_t ss = si * sh;
00946          SetValue(cj * ch, sj * sc - cs, sj * cc + ss,
00947                   cj * sh, sj * ss + cc, sj * cs - sc,
00948                   -sj, cj * si, cj * ci);
00949       }
00950 
00951       void Scale(Double_t x, Double_t y, Double_t z)
00952       {
00953          fEl[0][0] *= x; fEl[0][1] *= y; fEl[0][2] *= z;
00954          fEl[1][0] *= x; fEl[1][1] *= y; fEl[1][2] *= z;
00955          fEl[2][0] *= x; fEl[2][1] *= y; fEl[2][2] *= z;
00956       }
00957       TMatrix3x3 Scaled(Double_t x, Double_t y, Double_t z)const
00958       {
00959          return TMatrix3x3(fEl[0][0] * x, fEl[0][1] * y, fEl[0][2] * z,
00960                           fEl[1][0] * x, fEl[1][1] * y, fEl[1][2] * z,
00961                           fEl[2][0] * x, fEl[2][1] * y, fEl[2][2] * z);
00962       }
00963 
00964       void SetIdentity()
00965       {
00966          SetValue(1., 0., 0., 0., 1., 0., 0., 0., 1.);
00967       }
00968       void GetValue(Double_t *m)const
00969       {
00970          *m++ = fEl[0][0]; *m++ = fEl[1][0]; *m++ = fEl[2][0]; *m++ = 0.0;
00971          *m++ = fEl[0][1]; *m++ = fEl[1][1]; *m++ = fEl[2][1]; *m++ = 0.0;
00972          *m++ = fEl[0][2]; *m++ = fEl[1][2]; *m++ = fEl[2][2]; *m   = 0.0;
00973       }
00974 
00975       TMatrix3x3 &operator *= (const TMatrix3x3 &m);
00976       Double_t Tdot(Int_t c, const TVector3 &v)const
00977       {
00978          return fEl[0][c] * v[0] + fEl[1][c] * v[1] + fEl[2][c] * v[2];
00979       }
00980       Double_t Cofac(Int_t r1, Int_t c1, Int_t r2, Int_t c2)const
00981       {
00982          return fEl[r1][c1] * fEl[r2][c2] - fEl[r1][c2] * fEl[r2][c1];
00983       }
00984 
00985       Double_t  Determinant()const;
00986       TMatrix3x3 Adjoint()const;
00987       TMatrix3x3 Absolute()const;
00988       TMatrix3x3 Transposed()const;
00989       void      Transpose();
00990       TMatrix3x3 Inverse()const;
00991       void      Invert();
00992    };
00993 
00994    //______________________________________________________________________________
00995    TMatrix3x3 &TMatrix3x3::operator *= (const TMatrix3x3 &m)
00996    {
00997       //
00998       SetValue(m.Tdot(0, fEl[0]), m.Tdot(1, fEl[0]), m.Tdot(2, fEl[0]),
00999                m.Tdot(0, fEl[1]), m.Tdot(1, fEl[1]), m.Tdot(2, fEl[1]),
01000                m.Tdot(0, fEl[2]), m.Tdot(1, fEl[2]), m.Tdot(2, fEl[2]));
01001       return *this;
01002    }
01003 
01004    //______________________________________________________________________________
01005    Double_t TMatrix3x3::Determinant()const
01006    {
01007       //
01008       return triple((*this)[0], (*this)[1], (*this)[2]);
01009    }
01010 
01011    //______________________________________________________________________________
01012    TMatrix3x3 TMatrix3x3::Absolute()const
01013    {
01014       //
01015       return TMatrix3x3(TMath::Abs(fEl[0][0]), TMath::Abs(fEl[0][1]), TMath::Abs(fEl[0][2]),
01016                        TMath::Abs(fEl[1][0]), TMath::Abs(fEl[1][1]), TMath::Abs(fEl[1][2]),
01017                        TMath::Abs(fEl[2][0]), TMath::Abs(fEl[2][1]), TMath::Abs(fEl[2][2]));
01018    }
01019 
01020    //______________________________________________________________________________
01021    TMatrix3x3 TMatrix3x3::Transposed()const
01022    {
01023       //
01024       return TMatrix3x3(fEl[0][0], fEl[1][0], fEl[2][0],
01025                        fEl[0][1], fEl[1][1], fEl[2][1],
01026                        fEl[0][2], fEl[1][2], fEl[2][2]);
01027    }
01028 
01029    //______________________________________________________________________________
01030    void TMatrix3x3::Transpose()
01031    {
01032       //
01033       *this = Transposed();
01034    }
01035 
01036    //______________________________________________________________________________
01037    TMatrix3x3 TMatrix3x3::Adjoint()const
01038    {
01039       //
01040       return TMatrix3x3(Cofac(1, 1, 2, 2), Cofac(0, 2, 2, 1), Cofac(0, 1, 1, 2),
01041                        Cofac(1, 2, 2, 0), Cofac(0, 0, 2, 2), Cofac(0, 2, 1, 0),
01042                        Cofac(1, 0, 2, 1), Cofac(0, 1, 2, 0), Cofac(0, 0, 1, 1));
01043    }
01044 
01045    //______________________________________________________________________________
01046    TMatrix3x3 TMatrix3x3::Inverse()const
01047    {
01048       //
01049       TVector3 co(Cofac(1, 1, 2, 2), Cofac(1, 2, 2, 0), Cofac(1, 0, 2, 1));
01050       Double_t det = dot((*this)[0], co);
01051       Double_t s = 1. / det;
01052       return TMatrix3x3(co[0] * s, Cofac(0, 2, 2, 1) * s, Cofac(0, 1, 1, 2) * s,
01053                        co[1] * s, Cofac(0, 0, 2, 2) * s, Cofac(0, 2, 1, 0) * s,
01054                        co[2] * s, Cofac(0, 1, 2, 0) * s, Cofac(0, 0, 1, 1) * s);
01055    }
01056 
01057    //______________________________________________________________________________
01058    void TMatrix3x3::Invert()
01059    {
01060       //
01061       *this = Inverse();
01062    }
01063 
01064    //______________________________________________________________________________
01065    TVector3 operator * (const TMatrix3x3& m, const TVector3& v)
01066    {
01067       return TVector3(dot(m[0], v), dot(m[1], v), dot(m[2], v));
01068    }
01069 
01070    //______________________________________________________________________________
01071    TVector3 operator * (const TVector3& v, const TMatrix3x3& m)
01072    {
01073       return TVector3(m.Tdot(0, v), m.Tdot(1, v), m.Tdot(2, v));
01074    }
01075 
01076    //______________________________________________________________________________
01077    TMatrix3x3 operator * (const TMatrix3x3 &m1, const TMatrix3x3 &m2)
01078    {
01079       return TMatrix3x3(m2.Tdot(0, m1[0]), m2.Tdot(1, m1[0]), m2.Tdot(2, m1[0]),
01080                        m2.Tdot(0, m1[1]), m2.Tdot(1, m1[1]), m2.Tdot(2, m1[1]),
01081                        m2.Tdot(0, m1[2]), m2.Tdot(1, m1[2]), m2.Tdot(2, m1[2]));
01082    }
01083 
01084    //______________________________________________________________________________
01085    TMatrix3x3 mmult_transpose_left(const TMatrix3x3 &m1, const TMatrix3x3 &m2)
01086    {
01087       return TMatrix3x3(m1[0][0] * m2[0][0] + m1[1][0] * m2[1][0] + m1[2][0] * m2[2][0],
01088                        m1[0][0] * m2[0][1] + m1[1][0] * m2[1][1] + m1[2][0] * m2[2][1],
01089                        m1[0][0] * m2[0][2] + m1[1][0] * m2[1][2] + m1[2][0] * m2[2][2],
01090                        m1[0][1] * m2[0][0] + m1[1][1] * m2[1][0] + m1[2][1] * m2[2][0],
01091                        m1[0][1] * m2[0][1] + m1[1][1] * m2[1][1] + m1[2][1] * m2[2][1],
01092                        m1[0][1] * m2[0][2] + m1[1][1] * m2[1][2] + m1[2][1] * m2[2][2],
01093                        m1[0][2] * m2[0][0] + m1[1][2] * m2[1][0] + m1[2][2] * m2[2][0],
01094                        m1[0][2] * m2[0][1] + m1[1][2] * m2[1][1] + m1[2][2] * m2[2][1],
01095                        m1[0][2] * m2[0][2] + m1[1][2] * m2[1][2] + m1[2][2] * m2[2][2]);
01096    }
01097 
01098    //______________________________________________________________________________
01099    TMatrix3x3 mmult_transpose_right(const TMatrix3x3& m1, const TMatrix3x3& m2)
01100    {
01101       return TMatrix3x3(m1[0].Dot(m2[0]), m1[0].Dot(m2[1]), m1[0].Dot(m2[2]),
01102                        m1[1].Dot(m2[0]), m1[1].Dot(m2[1]), m1[1].Dot(m2[2]),
01103                        m1[2].Dot(m2[0]), m1[2].Dot(m2[1]), m1[2].Dot(m2[2]));
01104    }
01105 
01106    class TLine3 {
01107    private :
01108       Bool_t   fBounds[2];
01109       Double_t fParams[2];
01110       TPoint3   fOrigin;
01111       TVector3  fDir;
01112 
01113    public :
01114       TLine3();
01115       TLine3(const TPoint3 &p1, const TPoint3 &p2);
01116       TLine3(const TPoint3 &p1, const TVector3 &v);
01117       TLine3(const TPoint3 &p1, const TVector3 &v, Bool_t bound1, Bool_t bound2);
01118 
01119       static TLine3   InfiniteRay(const TPoint3 &p1, const TVector3 &v);
01120       const TVector3 &Direction()const {return fDir;}
01121       const TPoint3  &Origin()const{ return fOrigin;}
01122 
01123       Bool_t Bounds(Int_t i)const
01124       {
01125          return (i == 0 ? fBounds[0] : fBounds[1]);
01126       }
01127       Bool_t &Bounds(Int_t i)
01128       {
01129          return (i == 0 ? fBounds[0] : fBounds[1]);
01130       }
01131       const Double_t &Param(Int_t i)const
01132       {
01133          return (i == 0 ? fParams[0] : fParams[1]);
01134       }
01135       Double_t &Param(Int_t i)
01136       {
01137          return (i == 0 ? fParams[0] : fParams[1]);
01138       }
01139       TVector3 UnboundSmallestVector(const TPoint3 &point)const
01140       {
01141          TVector3 diff(fOrigin - point);
01142          return diff - fDir * diff.Dot(fDir);
01143       }
01144       Double_t UnboundClosestParameter(const TPoint3 &point)const
01145       {
01146          TVector3 diff(fOrigin-point);
01147          return diff.Dot(fDir);
01148       }
01149       Double_t UnboundDistance(const TPoint3& point)const
01150       {
01151          return UnboundSmallestVector(point).Length();
01152       }
01153       Bool_t IsParameterOnLine(const Double_t &t) const
01154       {
01155          return ((fParams[0] - epsilon < t) || (!fBounds[0])) && ((fParams[1] > t + epsilon) || (!fBounds[1]));
01156       }
01157    };
01158 
01159    //______________________________________________________________________________
01160    TLine3::TLine3() : fOrigin(0,0,0), fDir(1,0,0)
01161    {
01162       //
01163       fBounds[0] = kFALSE; fBounds[1] = kFALSE;
01164       fParams[0] = 0; fParams[1] = 1;
01165    }
01166 
01167    //______________________________________________________________________________
01168    TLine3::TLine3(const TPoint3 &p1, const TPoint3 &p2) : fOrigin(p1), fDir(p2-p1)
01169    {
01170       //
01171       fBounds[0] = kTRUE; fBounds[1] = kTRUE;
01172       fParams[0] = 0; fParams[1] = 1;
01173    }
01174 
01175    //______________________________________________________________________________
01176    TLine3::TLine3(const TPoint3 &p1, const TVector3 &v): fOrigin(p1), fDir(v)
01177    {
01178       //
01179       fBounds[0] = kFALSE; fBounds[1] = kFALSE;
01180       fParams[0] = 0; fParams[1] = 1;
01181    }
01182 
01183    //______________________________________________________________________________
01184    TLine3::TLine3(const TPoint3 &p1, const TVector3 &v, Bool_t bound1, Bool_t bound2)
01185             : fOrigin(p1), fDir(v)
01186    {
01187       //
01188       fBounds[0] = bound1; fBounds[1] = bound2;
01189       fParams[0] = 0; fParams[1] = 1;
01190    }
01191 
01192    class TPlane3 : public Tuple4 {
01193    public :
01194       TPlane3(const TVector3 &a, const TVector3 &b, const TVector3 &c);
01195       TPlane3(const TVector3 &n, const TVector3 &p);
01196       TPlane3();
01197       TPlane3(const TPlane3 & p):Tuple4(p){}
01198 
01199       TVector3  Normal()const;
01200       Double_t  Scalar()const;
01201       void     Invert();
01202       Double_t SignedDistance(const TVector3 &)const;
01203 
01204       TPlane3 &operator = (const TPlane3 & rhs);
01205    };
01206 
01207    //______________________________________________________________________________
01208    TPlane3::TPlane3(const TVector3 &a, const TVector3 &b, const TVector3 &c)
01209    {
01210       //
01211       TVector3 l1 = b-a;
01212       TVector3 l2 = c-b;
01213       TVector3 n = l1.Cross(l2);
01214       n = n.SafeNormalized();
01215       Double_t d = n.Dot(a);
01216       fCo[0] = n.X(); fCo[1] = n.Y(); fCo[2] = n.Z(); fCo[3] = -d;
01217    }
01218 
01219    //______________________________________________________________________________
01220    TPlane3::TPlane3(const TVector3 &n, const TVector3 &p)
01221    {
01222       //
01223       TVector3 mn = n.SafeNormalized();
01224       Double_t md = mn.Dot(p);
01225       fCo[0] = mn.X(); fCo[1] = mn.Y(); fCo[2] = mn.Z(); fCo[3] = -md;
01226    }
01227 
01228    //______________________________________________________________________________
01229    TPlane3::TPlane3() : Tuple4()
01230    {
01231       //
01232       fCo[0] = 1.; fCo[1] = 0.;
01233       fCo[2] = 0.; fCo[3] = 0.;
01234    }
01235 
01236    //______________________________________________________________________________
01237    TVector3 TPlane3::Normal()const
01238    {
01239       //
01240       return TVector3(fCo[0],fCo[1],fCo[2]);
01241    }
01242 
01243    //______________________________________________________________________________
01244    Double_t TPlane3::Scalar()const
01245    {
01246       //
01247       return fCo[3];
01248    }
01249 
01250    //______________________________________________________________________________
01251    void TPlane3::Invert()
01252    {
01253       //
01254       fCo[0] = -fCo[0]; fCo[1] = -fCo[1]; fCo[2] = -fCo[2]; fCo[3] = -fCo[3];
01255    }
01256 
01257    //______________________________________________________________________________
01258    TPlane3 &TPlane3::operator = (const TPlane3 &rhs)
01259    {
01260       //
01261       fCo[0] = rhs.fCo[0]; fCo[1] = rhs.fCo[1]; fCo[2] = rhs.fCo[2]; fCo[3] = rhs.fCo[3];
01262       return *this;
01263    }
01264 
01265    //______________________________________________________________________________
01266    Double_t TPlane3::SignedDistance(const TVector3 &v)const
01267    {
01268       //
01269       return Normal().Dot(v) + fCo[3];
01270    }
01271 
01272    class TBBox {
01273       friend Bool_t intersect(const TBBox &a, const TBBox &b);
01274 
01275    private:
01276       TPoint3  fCenter;
01277       TVector3 fExtent;
01278 
01279    public:
01280       TBBox(){}
01281       TBBox(const TPoint3 &mini, const TPoint3 &maxi){SetValue(mini,maxi);}
01282 
01283       const TPoint3   &Center()const{return fCenter;}
01284       const TVector3  &Extent()const{return fExtent;}
01285       TPoint3         &Center(){return fCenter;}
01286       TVector3        &Extent(){return fExtent;}
01287 
01288       void SetValue(const TPoint3 &mini,const TPoint3 &maxi)
01289       {
01290          fExtent = (maxi - mini) / 2;
01291          fCenter = mini + fExtent;
01292       }
01293       void Enclose(const TBBox &a, const TBBox &b)
01294       {
01295          TPoint3 lower(
01296             TMath::Min(a.Lower(0), b.Lower(0)),
01297             TMath::Min(a.Lower(1), b.Lower(1)),
01298             TMath::Min(a.Lower(2), b.Lower(2))
01299          );
01300          TPoint3 upper(
01301             TMath::Max(a.Upper(0), b.Upper(0)),
01302             TMath::Max(a.Upper(1), b.Upper(1)),
01303             TMath::Max(a.Upper(2), b.Upper(2))
01304          );
01305          SetValue(lower, upper);
01306       }
01307 
01308       void SetEmpty()
01309       {
01310          fCenter.SetValue(0., 0., 0.);
01311          fExtent.SetValue(-infinity, -infinity, -infinity);
01312       }
01313       void Include(const TPoint3 &p)
01314       {
01315          TPoint3 lower(
01316             TMath::Min(Lower(0), p[0]),
01317             TMath::Min(Lower(1), p[1]),
01318             TMath::Min(Lower(2), p[2])
01319          );
01320          TPoint3 upper(
01321             TMath::Max(Upper(0), p[0]),
01322             TMath::Max(Upper(1), p[1]),
01323             TMath::Max(Upper(2), p[2])
01324          );
01325          SetValue(lower, upper);
01326       }
01327 
01328       void Include(const TBBox &b)
01329       {
01330          Enclose(*this, b);
01331       }
01332       Double_t Lower(Int_t i)const
01333       {
01334          return fCenter[i] - fExtent[i];
01335       }
01336       Double_t Upper(Int_t i)const
01337       {
01338          return fCenter[i] + fExtent[i];
01339       }
01340       TPoint3 Lower()const
01341       {
01342          return fCenter - fExtent;
01343       }
01344       TPoint3 Upper()const
01345       {
01346          return fCenter + fExtent;
01347       }
01348       Double_t Size()const
01349       {
01350          return TMath::Max(TMath::Max(fExtent[0], fExtent[1]), fExtent[2]);
01351       }
01352       Int_t LongestAxis()const
01353       {
01354          return fExtent.ClosestAxis();
01355       }
01356       Bool_t IntersectXRay(const TPoint3 &xBase)const
01357       {
01358          if (xBase[0] <= Upper(0)) {
01359             if (xBase[1] <= Upper(1) && xBase[1] >= Lower(1)) {
01360                if (xBase[2] <= Upper(2) && xBase[2] >= Lower(2)) {return kTRUE;}
01361             }
01362          }
01363          return kFALSE;
01364       }
01365    };
01366 
01367    //______________________________________________________________________________
01368    Bool_t intersect(const TBBox &a, const TBBox &b)
01369    {
01370       return TMath::Abs(a.fCenter[0] - b.fCenter[0]) <= a.fExtent[0] + b.fExtent[0] &&
01371              TMath::Abs(a.fCenter[1] - b.fCenter[1]) <= a.fExtent[1] + b.fExtent[1] &&
01372              TMath::Abs(a.fCenter[2] - b.fCenter[2]) <= a.fExtent[2] + b.fExtent[2];
01373    }
01374 
01375    class TBBoxNode {
01376    public:
01377       enum ETagType {kLeaf, kInternal};
01378       TBBox     fBBox;
01379       ETagType fTag;
01380    };
01381 
01382    class TBBoxLeaf : public TBBoxNode {
01383    public:
01384       Int_t fPolyIndex;
01385 
01386       TBBoxLeaf() : fPolyIndex(0) {}
01387       TBBoxLeaf(Int_t polyIndex, const TBBox &bbox) : fPolyIndex(polyIndex)
01388       {
01389          fBBox = bbox;
01390          fTag = kLeaf;
01391       }
01392    };
01393 
01394    typedef TBBoxLeaf *LeafPtr_t;
01395    typedef TBBoxNode *NodePtr_t;
01396 
01397    class TBBoxInternal : public TBBoxNode {
01398    public:
01399       NodePtr_t fLeftSon;
01400       NodePtr_t fRightSon;
01401       TBBoxInternal() : fLeftSon(0) ,fRightSon(0) {}
01402       TBBoxInternal(Int_t n, LeafPtr_t leafIt);
01403    };
01404 
01405    typedef TBBoxInternal* InternalPtr_t;
01406 
01407    class TBBoxTree {
01408    private:
01409       Int_t         fBranch;
01410       LeafPtr_t     fLeaves;
01411       InternalPtr_t fInternals;
01412       Int_t         fNumLeaves;
01413 
01414    public :
01415       TBBoxTree() : fBranch(0), fLeaves(0), fInternals(0), fNumLeaves(0) {}
01416       NodePtr_t RootNode()const{return fInternals;}
01417       ~TBBoxTree()
01418       {
01419          delete[] fLeaves;
01420          delete[] fInternals;
01421       }
01422       void BuildTree(LeafPtr_t leaves, Int_t numLeaves);
01423 
01424    private :
01425       void RecursiveTreeBuild(Int_t n, LeafPtr_t leafIt);
01426    };
01427 
01428    //______________________________________________________________________________
01429    TBBoxInternal::TBBoxInternal(Int_t n, LeafPtr_t leafIt) :
01430       fLeftSon(0) ,fRightSon(0)
01431    {
01432       //
01433       fTag = kInternal;
01434       fBBox.SetEmpty();
01435       for (Int_t i=0;i<n;i++)
01436          fBBox.Include(leafIt[i].fBBox);
01437    }
01438 
01439    //______________________________________________________________________________
01440    void TBBoxTree::BuildTree(LeafPtr_t leaves, Int_t numLeaves)
01441    {
01442       //
01443       fBranch = 0;
01444       fLeaves = leaves;
01445       fNumLeaves = numLeaves;
01446       fInternals = new TBBoxInternal[numLeaves];
01447       RecursiveTreeBuild(fNumLeaves,fLeaves);
01448    }
01449 
01450    //______________________________________________________________________________
01451    void TBBoxTree::RecursiveTreeBuild(Int_t n, LeafPtr_t leafIt)
01452    {
01453       //
01454       fInternals[fBranch] = TBBoxInternal(n,leafIt);
01455       TBBoxInternal &aBBox = fInternals[fBranch];
01456       fBranch++;
01457 
01458       Int_t axis = aBBox.fBBox.LongestAxis();
01459       Int_t i = 0, mid = n;
01460 
01461       while (i < mid) {
01462          if (leafIt[i].fBBox.Center()[axis] < aBBox.fBBox.Center()[axis]) {
01463             ++i;
01464          } else {
01465             --mid;
01466             std::swap(leafIt[i], leafIt[mid]);
01467          }
01468       }
01469 
01470       if (mid == 0 || mid == n) {
01471          mid = n / 2;
01472       }
01473       if (mid >= 2) {
01474          aBBox.fRightSon = fInternals + fBranch;
01475          RecursiveTreeBuild(mid,leafIt);
01476       } else {
01477          aBBox.fRightSon = leafIt;
01478       }
01479       if (n - mid >= 2) {
01480          aBBox.fLeftSon = fInternals + fBranch;
01481          RecursiveTreeBuild(n - mid, leafIt + mid);
01482       } else {
01483          aBBox.fLeftSon = leafIt + mid;
01484       }
01485    }
01486 
01487    class TBlenderVProp {
01488    private:
01489       Int_t fVertexIndex;
01490 
01491    public:
01492       TBlenderVProp(Int_t vIndex) : fVertexIndex(vIndex){}
01493       TBlenderVProp(Int_t vIndex, const TBlenderVProp &,
01494                    const TBlenderVProp &, const Double_t &)
01495       {
01496          fVertexIndex = vIndex;
01497       }
01498       TBlenderVProp() : fVertexIndex(-1){}
01499       operator Int_t()const
01500       {
01501          return fVertexIndex;
01502       }
01503       TBlenderVProp &operator = (Int_t i)
01504       {
01505          fVertexIndex = i; return *this;
01506       }
01507    };
01508 
01509    template <class TMesh>
01510    class TPolygonGeometry {
01511    public:
01512       typedef typename TMesh::Polygon TPolygon;
01513 
01514    private:
01515       const TMesh    &fMesh;
01516       const TPolygon &fPoly;
01517    public:
01518       TPolygonGeometry(const TMesh &mesh, Int_t pIndex)
01519          : fMesh(mesh), fPoly(mesh.Polys()[pIndex])
01520       {}
01521       TPolygonGeometry(const TMesh &mesh, const TPolygon &poly)
01522          : fMesh(mesh), fPoly(poly)
01523       {}
01524       const TPoint3 &operator [] (Int_t i)const
01525       {
01526          return fMesh.Verts()[fPoly[i]].Pos();
01527       }
01528       Int_t Size()const
01529       {
01530          return fPoly.Size();
01531       }
01532 
01533    private:
01534       TPolygonGeometry(const TPolygonGeometry &);
01535       TPolygonGeometry& operator = (TPolygonGeometry &);
01536    };
01537 
01538    template <class TPolygon, class TVertex>
01539    class TMesh : public TBaseMesh {
01540    public:
01541       typedef std::vector<TVertex> VLIST;
01542       typedef std::vector<TPolygon> PLIST;
01543       typedef TPolygon Polygon;
01544       typedef TVertex Vertex;
01545       typedef TPolygonGeometry<TMesh> TGBinder;
01546 
01547    private:
01548       VLIST fVerts;
01549       PLIST fPolys;
01550 
01551    public:
01552       VLIST       &Verts(){return fVerts;}
01553       const VLIST &Verts()const{return fVerts;}
01554       PLIST       &Polys(){return fPolys;}
01555       const PLIST &Polys()const{return fPolys;}
01556 
01557       //TBaseMesh's final-overriders
01558       UInt_t          NumberOfPolys()const{return fPolys.size();}
01559       UInt_t          NumberOfVertices()const{return fVerts.size();}
01560       UInt_t          SizeOfPoly(UInt_t polyIndex)const{return fPolys[polyIndex].Size();}
01561       const Double_t *GetVertex(UInt_t vertexNum)const{return fVerts[vertexNum].GetValue();}
01562 
01563       Int_t GetVertexIndex(UInt_t polyNum, UInt_t vertexNum)const
01564       {
01565          return fPolys[polyNum][vertexNum];
01566       }
01567    };
01568 
01569    const Int_t cofacTable[3][2] = {{1,2}, {0,2}, {0,1}};
01570 
01571    //______________________________________________________________________________
01572    Bool_t intersect(const TPlane3 &p1, const TPlane3 &p2, TLine3 &output)
01573    {
01574       TMatrix3x3 mat;
01575       mat[0] = p1.Normal();
01576       mat[1] = p2.Normal();
01577       mat[2] = mat[0].Cross(mat[1]);
01578       if (mat[2].FuzzyZero()) return kFALSE;
01579       TVector3 aPoint(-p1.Scalar(),-p2.Scalar(),0);
01580       output = TLine3(TPoint3(0., 0., 0.) + mat.Inverse() * aPoint ,mat[2]);
01581       return kTRUE;
01582    }
01583 
01584    //______________________________________________________________________________
01585    Bool_t intersect_2d_no_bounds_check(const TLine3 &l1, const TLine3 &l2, Int_t majAxis,
01586                                        Double_t &l1Param, Double_t &l2Param)
01587    {
01588       Int_t ind1 = cofacTable[majAxis][0];
01589       Int_t ind2 = cofacTable[majAxis][1];
01590       Double_t zX = l2.Origin()[ind1] - l1.Origin()[ind1];
01591       Double_t zY = l2.Origin()[ind2] - l1.Origin()[ind2];
01592       Double_t det = l1.Direction()[ind1]*l2.Direction()[ind2] -
01593                      l2.Direction()[ind1]*l1.Direction()[ind2];
01594       if (fuzzy_zero(det)) return kFALSE;
01595       l1Param = (l2.Direction()[ind2] * zX - l2.Direction()[ind1] * zY)/det;
01596       l2Param = -(-l1.Direction()[ind2] * zX + l1.Direction()[ind1] * zY)/det;
01597       return kTRUE;
01598    }
01599 
01600    //______________________________________________________________________________
01601    Bool_t intersect_2d_bounds_check(const TLine3 &l1, const TLine3 &l2, Int_t majAxis,
01602                                     Double_t &l1Param, Double_t &l2Param)
01603    {
01604       Bool_t isect = intersect_2d_no_bounds_check(l1, l2, majAxis, l1Param, l2Param);
01605       if (!isect) return kFALSE;
01606       return l1.IsParameterOnLine(l1Param) && l2.IsParameterOnLine(l2Param);
01607    }
01608 
01609    //______________________________________________________________________________
01610    Int_t compute_classification(const Double_t &distance, const Double_t &epsil)
01611    {
01612       if (TMath::Abs(distance) < epsil) return 0;
01613       else return distance < 0 ? 1 : 2;
01614    }
01615 
01616    //______________________________________________________________________________
01617    template<typename TGBinder>
01618    Bool_t intersect_poly_with_line_2d(const TLine3 &l, const TGBinder &p1, const TPlane3 &plane,
01619                                       Double_t &a, Double_t &b)
01620    {
01621       Int_t majAxis = plane.Normal().ClosestAxis();
01622       Int_t lastInd = p1.Size()-1;
01623       b = (-infinity); a = (infinity);
01624       Double_t isectParam(0.), isectParam2(0.);
01625       Int_t i;
01626       Int_t j = lastInd;
01627       Int_t isectsFound(0);
01628       for (i=0;i<=lastInd; j=i,i++ ) {
01629          TLine3 testLine(p1[j],p1[i]);
01630          if (intersect_2d_bounds_check(l, testLine, majAxis, isectParam, isectParam2)) {
01631             ++isectsFound;
01632             b = TMath::Max(isectParam, b);
01633             a = TMath::Min(isectParam, a);
01634          }
01635       }
01636 
01637       return (isectsFound > 0);
01638    }
01639 
01640    //______________________________________________________________________________
01641    template<typename TGBinder>
01642    Bool_t instersect_poly_with_line_3d(const TLine3 &l, const TGBinder &p1,
01643                                        const TPlane3 &plane, Double_t &a)
01644    {
01645       Double_t determinant = l.Direction().Dot(plane.Normal());
01646       if (fuzzy_zero(determinant)) return kFALSE;
01647       a = -plane.Scalar() - plane.Normal().Dot(l.Origin());
01648       a /= determinant;
01649       if (a <= 0 ) return kFALSE;
01650       if (!l.IsParameterOnLine(a)) return kFALSE;
01651       TPoint3 pointOnPlane = l.Origin() + l.Direction() * a;
01652       return point_in_polygon_test_3d(p1, plane, l.Origin(), pointOnPlane);
01653    }
01654 
01655    //______________________________________________________________________________
01656    template<typename TGBinder>
01657    Bool_t point_in_polygon_test_3d(const TGBinder& p1, const TPlane3& plane, const TPoint3& origin,
01658                                    const TPoint3 &pointOnPlane)
01659    {
01660       Bool_t discardSign = plane.SignedDistance(origin) < 0 ? kTRUE : kFALSE;
01661       const Int_t polySize = p1.Size();
01662       TPoint3 lastPoint = p1[polySize-1];
01663       for (Int_t i=0;i<polySize; ++i) {
01664          const TPoint3& aPoint = p1[i];
01665          TPlane3 testPlane(origin, lastPoint, aPoint);
01666          if ((testPlane.SignedDistance(pointOnPlane) <= 0) == discardSign) return kFALSE;
01667          lastPoint = aPoint;
01668       }
01669 
01670       return kTRUE;
01671    }
01672 
01673    //______________________________________________________________________________
01674    template <typename TGBinder>
01675    TPoint3 polygon_mid_point(const TGBinder &p1)
01676    {
01677       TPoint3 midPoint(0., 0., 0.);
01678       Int_t i;
01679       for (i=0; i < p1.Size(); i++)
01680          midPoint += p1[i];
01681       return TPoint3(midPoint[0] / i, midPoint[1] / i, midPoint[2] / i);
01682    }
01683 
01684    //______________________________________________________________________________
01685    template <typename TGBinder>
01686    Int_t which_side(const TGBinder &p1, const TPlane3 &plane1)
01687    {
01688       Int_t output = 0;
01689       Int_t i;
01690       for (i=0; i<p1.Size(); i++) {
01691          Double_t signedDistance = plane1.SignedDistance(p1[i]);
01692          if (!fuzzy_zero(signedDistance))
01693             signedDistance < 0 ? (output |= 1) : (output |=2);
01694       }
01695 
01696       return output;
01697    }
01698 
01699    //______________________________________________________________________________
01700    template <typename TGBinder>
01701    TLine3 polygon_mid_point_ray(const TGBinder &p1, const TPlane3 &plane)
01702    {
01703       return TLine3(polygon_mid_point(p1),plane.Normal(),kTRUE,kFALSE);
01704    }
01705 
01706    //______________________________________________________________________________
01707    template <typename TGBinder>
01708    TPlane3 compute_plane(const TGBinder &poly)
01709    {
01710       TPoint3 plast(poly[poly.Size()-1]);
01711       TPoint3 pivot;
01712       TVector3 edge;
01713       Int_t j;
01714       for (j = 0; j < poly.Size(); j++) {
01715          pivot = poly[j];
01716          edge =  pivot - plast;
01717          if (!edge.FuzzyZero()) break;
01718       }
01719       for (; j < poly.Size(); j++) {
01720          TVector3 v2 = poly[j] - pivot;
01721          TVector3 v3 = edge.Cross(v2);
01722          if (!v3.FuzzyZero())
01723             return TPlane3(v3,pivot);
01724       }
01725 
01726       return TPlane3();
01727    }
01728 
01729    //______________________________________________________________________________
01730    template <typename TGBinder>
01731    TBBox fit_bbox(const TGBinder &p1)
01732    {
01733       TBBox bbox; bbox.SetEmpty();
01734       for (Int_t i = 0; i < p1.Size(); ++i)
01735          bbox.Include(p1[i]);
01736       return bbox;
01737    }
01738 
01739    //______________________________________________________________________________
01740    template<typename TGBinderA, typename TGBinderB>
01741    Bool_t intersect_polygons (const TGBinderA &p1, const TGBinderB &p2,
01742                               const TPlane3 &plane1, const TPlane3 &plane2)
01743    {
01744       TLine3 intersectLine;
01745       if (!intersect(plane1, plane2, intersectLine))
01746          return kFALSE;
01747       Double_t p1A, p1B;
01748       Double_t p2A, p2B;
01749       if (
01750           !intersect_poly_with_line_2d(intersectLine,p1,plane1,p1A,p1B) ||
01751           !intersect_poly_with_line_2d(intersectLine,p2,plane2,p2A,p2B))
01752       {
01753          return kFALSE;
01754       }
01755       Double_t maxOMin = TMath::Max(p1A,p2A);
01756       Double_t minOMax = TMath::Min(p1B,p2B);
01757       return (maxOMin <= minOMax);
01758    }
01759 
01760    template <class TMesh, class TSplitFunctionBinder>
01761    class TSplitFunction {
01762    private:
01763       TMesh                &fMesh;
01764       TSplitFunctionBinder &fFunctionBinder;
01765 
01766    public:
01767       TSplitFunction(TMesh &mesh, TSplitFunctionBinder &functionBindor)
01768          : fMesh(mesh), fFunctionBinder(functionBindor)
01769       {}
01770       void SplitPolygon(const Int_t p1Index, const TPlane3 &plane,
01771                         Int_t &inPiece, Int_t &outPiece,
01772                         const Double_t onEpsilon)
01773       {
01774          const typename TMesh::Polygon &p = fMesh.Polys()[p1Index];
01775          typename TMesh::Polygon inP(p),outP(p);
01776          inP.Verts().clear();
01777          outP.Verts().clear();
01778          fFunctionBinder.DisconnectPolygon(p1Index);
01779          Int_t lastIndex = p.Verts().back();
01780          TPoint3 lastVertex = fMesh.Verts()[lastIndex].Pos();
01781          Int_t lastClassification = compute_classification(plane.SignedDistance(lastVertex),onEpsilon);
01782          Int_t totalClassification(lastClassification);
01783          Int_t i;
01784          Int_t j=p.Size()-1;
01785          for (i = 0; i < p.Size(); j = i, ++i)
01786          {
01787             Int_t newIndex = p[i];
01788             TPoint3 aVertex = fMesh.Verts()[newIndex].Pos();
01789             Int_t newClassification = compute_classification(plane.SignedDistance(aVertex),onEpsilon);
01790             if ((newClassification != lastClassification) && newClassification && lastClassification)
01791             {
01792                Int_t newVertexIndex = fMesh.Verts().size();
01793                typedef typename TMesh::Vertex VERTEX_t;
01794                fMesh.Verts().push_back(VERTEX_t());
01795                TVector3 v = aVertex - lastVertex;
01796                Double_t sideA = plane.SignedDistance(lastVertex);
01797                Double_t epsil = -sideA / plane.Normal().Dot(v);
01798                fMesh.Verts().back().Pos() = lastVertex + (v * epsil);
01799                typename TMesh::Polygon::TVProp splitProp(newVertexIndex,p.VertexProps(j),p.VertexProps(i),epsil);
01800                inP.Verts().push_back(  splitProp );
01801                outP.Verts().push_back( splitProp );
01802                fFunctionBinder.InsertVertexAlongEdge(lastIndex,newIndex,splitProp);
01803             }
01804             Classify(inP.Verts(),outP.Verts(),newClassification, p.VertexProps(i));
01805             lastClassification = newClassification;
01806             totalClassification |= newClassification;
01807             lastVertex = aVertex;
01808             lastIndex = newIndex;
01809          }
01810          if (totalClassification == 3) {
01811             inPiece = p1Index;
01812             outPiece = fMesh.Polys().size();
01813             fMesh.Polys()[p1Index] = inP;
01814             fMesh.Polys().push_back(outP);
01815             fFunctionBinder.ConnectPolygon(inPiece);
01816             fFunctionBinder.ConnectPolygon(outPiece);
01817          } else {
01818             fFunctionBinder.ConnectPolygon(p1Index);
01819             if (totalClassification == 1) {
01820                inPiece = p1Index;
01821                outPiece = -1;
01822             } else {
01823                outPiece = p1Index;
01824                inPiece = -1;
01825             }
01826          }
01827       }
01828 
01829       void Classify(typename TMesh::Polygon::TVPropList &inGroup,
01830                     typename TMesh::Polygon::TVPropList &outGroup,
01831                     Int_t classification,
01832                     typename TMesh::Polygon::TVProp prop)
01833       {
01834          switch (classification) {
01835          case 0 :
01836             inGroup.push_back(prop);
01837             outGroup.push_back(prop);
01838             break;
01839          case 1 :
01840             inGroup.push_back(prop);
01841             break;
01842          case 2 :
01843             outGroup.push_back(prop);
01844             break;
01845          default :
01846             break;
01847          }
01848       }
01849 
01850    };
01851 
01852    template <typename PROP>
01853    class TDefaultSplitFunctionBinder {
01854    public :
01855       void DisconnectPolygon(Int_t){}
01856       void ConnectPolygon(Int_t){}
01857       void InsertVertexAlongEdge(Int_t, Int_t, const PROP &){}
01858    };
01859 
01860    template <typename TMesh>
01861    class TMeshWrapper {
01862    private :
01863       TMesh &fMesh;
01864 
01865    public:
01866       typedef typename TMesh::Polygon Polygon;
01867       typedef typename TMesh::Vertex Vertex;
01868       typedef typename TMesh::VLIST VLIST;
01869       typedef typename TMesh::PLIST PLIST;
01870       typedef TPolygonGeometry<TMeshWrapper> TGBinder;
01871       typedef TMeshWrapper<TMesh> MyType;
01872 
01873    public:
01874       TMeshWrapper(TMesh &mesh):fMesh(mesh){}
01875 
01876       VLIST       &Verts(){return fMesh.Verts();}
01877       const VLIST &Verts()const{return fMesh.Verts();}
01878       PLIST       &Polys(){return fMesh.Polys();}
01879       const PLIST &Polys() const {return fMesh.Polys();}
01880 
01881       void         ComputePlanes();
01882       TBBox         ComputeBBox()const;
01883       void         SplitPolygon(Int_t p1Index, const TPlane3 &plane,
01884                                 Int_t &inPiece, Int_t &outPiece, Double_t onEpsilon);
01885    };
01886 
01887    //______________________________________________________________________________
01888    template <typename TMesh>
01889    void TMeshWrapper<TMesh>::ComputePlanes()
01890    {
01891       //
01892       PLIST& polyList = Polys();
01893       UInt_t i;
01894       for (i=0;i < polyList.size(); i++) {
01895          TGBinder binder(fMesh,i);
01896          polyList[i].SetPlane(compute_plane(binder));
01897       }
01898    }
01899 
01900    //______________________________________________________________________________
01901    template <typename TMesh>
01902    TBBox TMeshWrapper<TMesh>::ComputeBBox()const
01903    {
01904       //
01905       const VLIST &vertexList = Verts();
01906       TBBox bbox;
01907       bbox.SetEmpty();
01908       Int_t i;
01909       for (i=0;i<vertexList.size(); i++)
01910          bbox.Include(vertexList[i].Pos());
01911       return bbox;
01912    }
01913 
01914    //______________________________________________________________________________
01915    template<typename TMesh>
01916    void TMeshWrapper<TMesh>::SplitPolygon(Int_t p1Index, const TPlane3 &plane,
01917                                          Int_t &inPiece, Int_t &outPiece,
01918                                          Double_t onEpsilon)
01919    {
01920       typedef typename TMesh::Polygon::TVProp mesh;
01921       TDefaultSplitFunctionBinder<mesh> defaultSplitFunction;
01922       TSplitFunction<MyType,TDefaultSplitFunctionBinder<mesh> >
01923          splitFunction(*this,defaultSplitFunction);
01924       splitFunction.SplitPolygon(p1Index,plane,inPiece,outPiece,onEpsilon);
01925    }
01926 
01927    template <typename AVProp, typename AFProp>
01928    class TPolygonBase {
01929    public:
01930       typedef AVProp TVProp;
01931       typedef AFProp TFProp;
01932       typedef std::vector<TVProp> TVPropList;
01933       typedef typename TVPropList::iterator TVPropIt;
01934 
01935    private :
01936       TVPropList fVerts;
01937       TPlane3     fPlane;
01938       TFProp     fFaceProp;
01939       Int_t      fClassification;
01940 
01941    public:
01942       const TVPropList &Verts()const{return fVerts;}
01943       TVPropList       &Verts(){return fVerts;}
01944       Int_t             Size()const{return Int_t(fVerts.size());}
01945 
01946       Int_t operator[](Int_t i) const {return fVerts[i];}
01947 
01948       const TVProp &VertexProps(Int_t i)const{return fVerts[i];}
01949       TVProp       &VertexProps(Int_t i){return fVerts[i];}
01950       void          SetPlane(const TPlane3 &plane){fPlane = plane;}
01951       const TPlane3 &Plane()const{return fPlane;}
01952       TVector3       Normal()const{return fPlane.Normal();}
01953       Int_t        &Classification(){ return fClassification;}
01954       const Int_t  &Classification()const{return fClassification;}
01955 
01956       void Reverse()
01957       {
01958          std::reverse(fVerts.begin(),fVerts.end());
01959          fPlane.Invert();
01960       }
01961 
01962       TFProp       &FProp(){return fFaceProp;}
01963       const TFProp &FProp()const{return fFaceProp;}
01964       void          AddProp(const TVProp &prop){fVerts.push_back(prop);}
01965    };
01966 
01967    typedef std::vector<Int_t> PIndexList_t;
01968    typedef PIndexList_t::iterator PIndexIt_t;
01969    typedef std::vector< PIndexList_t > OverlapTable_t;
01970 
01971    template <typename TMesh>
01972    class TreeIntersector {
01973    private:
01974       OverlapTable_t *fAoverlapsB;
01975       OverlapTable_t *fBoverlapsA;
01976       const TMesh    *fMeshA;
01977       const TMesh    *fMeshB;
01978 
01979    public :
01980       TreeIntersector(const TBBoxTree &a, const TBBoxTree &b,
01981                       OverlapTable_t *aOverlapsB, OverlapTable_t *bOverlapsA,
01982                       const TMesh *meshA, const TMesh *meshB)
01983       {
01984          fAoverlapsB = aOverlapsB;
01985          fBoverlapsA = bOverlapsA;
01986          fMeshA = meshA;
01987          fMeshB = meshB;
01988          MarkIntersectingPolygons(a.RootNode(),b.RootNode());
01989       }
01990 
01991    private :
01992       void MarkIntersectingPolygons(const TBBoxNode *a, const TBBoxNode *b)
01993       {
01994          if (!intersect(a->fBBox, b->fBBox)) return;
01995          if (a->fTag == TBBoxNode::kLeaf && b->fTag == TBBoxNode::kLeaf) {
01996             const TBBoxLeaf *la = (const TBBoxLeaf *)a;
01997             const TBBoxLeaf *lb = (const TBBoxLeaf *)b;
01998 
01999             TPolygonGeometry<TMesh> pg1(*fMeshA,la->fPolyIndex);
02000             TPolygonGeometry<TMesh> pg2(*fMeshB,lb->fPolyIndex);
02001 
02002             if (intersect_polygons(pg1, pg2, fMeshA->Polys()[la->fPolyIndex].Plane(),
02003                 fMeshB->Polys()[lb->fPolyIndex].Plane())) {
02004                (*fAoverlapsB)[lb->fPolyIndex].push_back(la->fPolyIndex);
02005                (*fBoverlapsA)[la->fPolyIndex].push_back(lb->fPolyIndex);
02006             }
02007          } else if ( a->fTag == TBBoxNode::kLeaf || (b->fTag != TBBoxNode::kLeaf && a->fBBox.Size() < b->fBBox.Size()))
02008          {
02009             MarkIntersectingPolygons(a, ((const TBBoxInternal *)b)->fLeftSon);
02010             MarkIntersectingPolygons(a, ((const TBBoxInternal *)b)->fRightSon);
02011          } else {
02012             MarkIntersectingPolygons(((const TBBoxInternal *)a)->fLeftSon, b);
02013             MarkIntersectingPolygons(((const TBBoxInternal *)a)->fRightSon, b);
02014          }
02015       }
02016    };
02017 
02018    template<typename TMesh>
02019    class TRayTreeIntersector {
02020    private:
02021       const TMesh *fMeshA;
02022       Double_t     fLastIntersectValue;
02023       Int_t        fPolyIndex;
02024 
02025    public:
02026       TRayTreeIntersector(const TBBoxTree &a, const TMesh *meshA, const TLine3 &xRay, Int_t &polyIndex)
02027          : fMeshA(meshA), fLastIntersectValue(infinity), fPolyIndex(-1)
02028       {
02029          FindIntersectingPolygons(a.RootNode(),xRay);
02030          polyIndex = fPolyIndex;
02031       }
02032 
02033    private :
02034       void FindIntersectingPolygons(const TBBoxNode*a,const TLine3& xRay)
02035       {
02036          if ((xRay.Origin().X() + fLastIntersectValue < a->fBBox.Lower(0)) ||!a->fBBox.IntersectXRay(xRay.Origin()))
02037             return;
02038          if (a->fTag == TBBoxNode::kLeaf) {
02039             const TBBoxLeaf *la = (const TBBoxLeaf *)a;
02040             Double_t testParameter(0.);
02041             TPolygonGeometry<TMesh> pg(*fMeshA, la->fPolyIndex);
02042             if (instersect_poly_with_line_3d(xRay,pg,fMeshA->Polys()[la->fPolyIndex].Plane(),testParameter))
02043             {
02044                if (testParameter < fLastIntersectValue) {
02045                   fLastIntersectValue = testParameter;
02046                   fPolyIndex = la->fPolyIndex;
02047                }
02048             }
02049          } else {
02050             FindIntersectingPolygons(((const TBBoxInternal*)a)->fLeftSon, xRay);
02051             FindIntersectingPolygons(((const TBBoxInternal*)a)->fRightSon, xRay);
02052          }
02053       }
02054    };
02055 
02056    class TVertexBase {
02057    protected:
02058       Int_t  fVertexMap;
02059       TPoint3 fPos;
02060 
02061    public:
02062       TVertexBase(Double_t x, Double_t y, Double_t z) : fVertexMap(-1), fPos(x, y, z){}
02063       TVertexBase():fVertexMap(-1) {}
02064 
02065       const TPoint3 &Pos()const{return fPos;}
02066       TPoint3       &Pos(){return fPos;}
02067       Int_t        &VertexMap(){return fVertexMap;}
02068       const Int_t  &VertexMap()const{return fVertexMap;}
02069       const Double_t * GetValue()const{return fPos.GetValue();}
02070 
02071       Double_t operator [] (Int_t ind)const{return fPos[ind];}
02072    };
02073 
02074    class TCVertex : public TVertexBase {
02075    private:
02076       PIndexList_t fPolygons;
02077    public:
02078       TCVertex() : TVertexBase(){}
02079       TCVertex(const TVertexBase& vertex) : TVertexBase(vertex){}
02080 
02081       TCVertex &operator = (const TVertexBase &other)
02082       {
02083          fPos= other.Pos();
02084          return *this;
02085       }
02086       const PIndexList_t &Polys()const{return fPolygons;}
02087       PIndexList_t       &Polys(){return fPolygons;}
02088 
02089       Int_t       &operator [] (Int_t i) { return fPolygons[i];}
02090       const Int_t &operator [] (Int_t i)const{return fPolygons[i];}
02091 
02092       void AddPoly(Int_t polyIndex){fPolygons.push_back(polyIndex);}
02093       void RemovePolygon(Int_t polyIndex)
02094       {
02095          PIndexIt_t foundIt = std::find(fPolygons.begin(), fPolygons.end(), polyIndex);
02096          if (foundIt != fPolygons.end()) {
02097             std::swap(fPolygons.back(), *foundIt);
02098             fPolygons.pop_back();
02099          }
02100       }
02101    };
02102 
02103    template <typename TMesh>
02104    class TConnectedMeshWrapper {
02105    private:
02106       TMesh  &fMesh;
02107       UInt_t  fUniqueEdgeTestId;
02108    public:
02109       typedef typename TMesh::Polygon Polygon;
02110       typedef typename TMesh::Vertex Vertex;
02111       typedef typename TMesh::Polygon::TVProp VProp;
02112       typedef typename TMesh::VLIST VLIST;
02113       typedef typename TMesh::PLIST PLIST;
02114       typedef TPolygonGeometry<TConnectedMeshWrapper> TGBinder;
02115       typedef TConnectedMeshWrapper<TMesh> MyType;
02116 
02117       TConnectedMeshWrapper(TMesh &mesh) : fMesh(mesh), fUniqueEdgeTestId(0){}
02118 
02119       VLIST       &Verts(){return fMesh.Verts();}
02120       const VLIST &Verts()const{return fMesh.Verts();}
02121       PLIST       &Polys() {return fMesh.Polys();}
02122       const PLIST &Polys() const {return fMesh.Polys();}
02123       void         BuildVertexPolyLists();
02124       void         DisconnectPolygon(Int_t polyIndex);
02125       void         ConnectPolygon(Int_t polyIndex);
02126       //return the polygons neibouring the given edge.
02127       void         EdgePolygons(Int_t v1, Int_t v2, PIndexList_t &polys);
02128       void         InsertVertexAlongEdge(Int_t v1,Int_t v2, const VProp &prop);
02129       void         SplitPolygon(Int_t p1Index, const TPlane3 &plane, Int_t &inPiece,
02130                                 Int_t &outPiece, Double_t onEpsilon);
02131    };
02132 
02133    template <class CMesh> class TSplitFunctionBinder {
02134    private:
02135       CMesh &fMesh;
02136 
02137    public:
02138       TSplitFunctionBinder(CMesh &mesh):fMesh(mesh){}
02139       void DisconnectPolygon(Int_t polyIndex){fMesh.DisconnectPolygon(polyIndex);}
02140       void ConnectPolygon(Int_t polygonIndex){fMesh.ConnectPolygon(polygonIndex);}
02141       void InsertVertexAlongEdge(Int_t lastIndex, Int_t newIndex, const typename CMesh::VProp &prop)
02142       {
02143          fMesh.InsertVertexAlongEdge(lastIndex, newIndex,prop);
02144       }
02145    };
02146 
02147    //______________________________________________________________________________
02148    template <typename TMesh>
02149    void TConnectedMeshWrapper<TMesh>::BuildVertexPolyLists()
02150    {
02151       //
02152       UInt_t i;
02153       for (i=0; i < Polys().size(); i++)
02154          ConnectPolygon(i);
02155    }
02156 
02157    //______________________________________________________________________________
02158    template <typename TMesh>
02159    void TConnectedMeshWrapper<TMesh>::DisconnectPolygon(Int_t polyIndex)
02160    {
02161       //
02162       const Polygon &poly = Polys()[polyIndex];
02163       UInt_t j;
02164       for (j=0;j<poly.Verts().size(); j++) {
02165          Verts()[poly[j]].RemovePolygon(polyIndex);
02166       }
02167    }
02168 
02169    //______________________________________________________________________________
02170    template <typename TMesh>
02171    void TConnectedMeshWrapper<TMesh>::ConnectPolygon(Int_t polyIndex)
02172    {
02173       //
02174       const Polygon &poly = Polys()[polyIndex];
02175       UInt_t j;
02176       for (j=0;j<poly.Verts().size(); j++) {
02177          Verts()[poly[j]].AddPoly(polyIndex);
02178       }
02179    }
02180 
02181    //______________________________________________________________________________
02182    template <typename TMesh>
02183    void TConnectedMeshWrapper<TMesh>::EdgePolygons(Int_t v1, Int_t v2, PIndexList_t &polys)
02184    {
02185       //
02186       ++fUniqueEdgeTestId;
02187       Vertex &vb1 = Verts()[v1];
02188       UInt_t i;
02189       for (i=0;i < vb1.Polys().size(); ++i){Polys()[vb1[i]].Classification() = fUniqueEdgeTestId;}
02190       Vertex &vb2 = Verts()[v2];
02191       UInt_t j;
02192       for (j=0;j < vb2.Polys().size(); ++j) {
02193          if ((UInt_t)Polys()[vb2[j]].Classification() == fUniqueEdgeTestId) {
02194             polys.push_back(vb2[j]);
02195          }
02196       }
02197    }
02198 
02199    //______________________________________________________________________________
02200    template <typename TMesh>
02201    void TConnectedMeshWrapper<TMesh>::InsertVertexAlongEdge(Int_t v1, Int_t v2, const VProp &prop)
02202    {
02203       //
02204       PIndexList_t npolys;
02205       EdgePolygons(v1,v2,npolys);
02206       Int_t newVertex = Int_t(prop);
02207       UInt_t i;
02208       for (i=0;i < npolys.size(); i++) {
02209          typename Polygon::TVPropList& polyVerts = Polys()[npolys[i]].Verts();
02210          typename Polygon::TVPropIt v1pos = std::find(polyVerts.begin(),polyVerts.end(),v1);
02211          if (v1pos != polyVerts.end()) {
02212             typename Polygon::TVPropIt prevPos = (v1pos == polyVerts.begin()) ? polyVerts.end()-1 : v1pos-1;
02213             typename Polygon::TVPropIt nextPos = (v1pos == polyVerts.end()-1) ? polyVerts.begin() : v1pos+1;
02214             if (*prevPos == v2) {
02215                polyVerts.insert(v1pos,prop);
02216             } else if (*nextPos == v2) {
02217                polyVerts.insert(nextPos, prop);
02218             } else {
02219                //assert(kFALSE);
02220             }
02221             Verts()[newVertex].AddPoly(npolys[i]);
02222          } else {
02223             //assert(kFALSE);
02224          }
02225       }
02226    }
02227 
02228    //______________________________________________________________________________
02229    template <typename TMesh>
02230    void TConnectedMeshWrapper<TMesh>::SplitPolygon(Int_t p1Index, const TPlane3 &plane,
02231                                                   Int_t &inPiece, Int_t &outPiece,
02232                                                   Double_t onEpsilon)
02233    {
02234       TSplitFunctionBinder<MyType> functionBindor(*this);
02235       TSplitFunction<MyType,TSplitFunctionBinder<MyType> > splitFunction(*this,functionBindor);
02236       splitFunction.SplitPolygon(p1Index, plane, inPiece, outPiece, onEpsilon);
02237    }
02238 
02239    struct NullType_t{};
02240    //Original TestPolygon_t has two parameters, the second is face property
02241 
02242    typedef TPolygonBase<TBlenderVProp, NullType_t> TestPolygon_t;
02243    typedef TMesh<TestPolygon_t,TVertexBase> AMesh_t;
02244    typedef TMesh<TestPolygon_t,TCVertex > AConnectedMesh_t;
02245    typedef TMeshWrapper<AMesh_t> AMeshWrapper_t;
02246    typedef TConnectedMeshWrapper<AConnectedMesh_t> AConnectedMeshWrapper_t;
02247 
02248    //______________________________________________________________________________
02249    template <class TMesh>
02250    void build_split_group(const TMesh &meshA, const TMesh &meshB,
02251                           const TBBoxTree &treeA, const TBBoxTree &treeB,
02252                           OverlapTable_t &aOverlapsB, OverlapTable_t &bOverlapsA)
02253    {
02254       aOverlapsB = OverlapTable_t(meshB.Polys().size());
02255       bOverlapsA = OverlapTable_t(meshA.Polys().size());
02256       TreeIntersector<TMesh>(treeA, treeB, &aOverlapsB, &bOverlapsA, &meshA, &meshB);
02257    }
02258 
02259    //______________________________________________________________________________
02260    template <class CMesh, class TMesh>
02261    void partition_mesh(CMesh &mesh, const TMesh &mesh2, const OverlapTable_t &table)
02262    {
02263       UInt_t i;
02264       Double_t onEpsilon(1e-4);
02265       for (i = 0; i < table.size(); i++) {
02266          if (table[i].size()) {
02267             PIndexList_t fragments;
02268             fragments.push_back(i);
02269             UInt_t j;
02270             for (j =0 ; j <table[i].size(); ++j) {
02271                PIndexList_t newFragments;
02272                TPlane3 splitPlane = mesh2.Polys()[table[i][j]].Plane();
02273                UInt_t k;
02274                for (k = 0; k < fragments.size(); ++k) {
02275                   Int_t newInFragment;
02276                   Int_t newOutFragment;
02277                   typename CMesh::TGBinder pg1(mesh,fragments[k]);
02278                   typename TMesh::TGBinder pg2(mesh2,table[i][j]);
02279                   const TPlane3 &fragPlane = mesh.Polys()[fragments[k]].Plane();
02280 
02281                   if (intersect_polygons(pg1,pg2,fragPlane,splitPlane)) {
02282                      mesh.SplitPolygon(fragments[k], splitPlane, newInFragment, newOutFragment, onEpsilon);
02283                      if (-1 != newInFragment) newFragments.push_back(newInFragment);
02284                      if (-1 != newOutFragment) newFragments.push_back(newOutFragment);
02285                   } else {
02286                      newFragments.push_back(fragments[k]);
02287                   }
02288                }
02289                fragments = newFragments;
02290             }
02291          }
02292       }
02293    }
02294 
02295    //______________________________________________________________________________
02296    template <typename CMesh, typename TMesh>
02297    void classify_mesh(const TMesh &meshA, const TBBoxTree &aTree, CMesh &meshB)
02298    {
02299       UInt_t i;
02300       for (i = 0; i < meshB.Polys().size(); i++) {
02301          typename CMesh::TGBinder pg(meshB,i);
02302          TLine3 midPointRay = polygon_mid_point_ray(pg,meshB.Polys()[i].Plane());
02303          TLine3 midPointXRay(midPointRay.Origin(),TVector3(1,0,0));
02304          Int_t aPolyIndex(-1);
02305          TRayTreeIntersector<TMesh>(aTree,&meshA,midPointXRay,aPolyIndex);
02306          if (-1 != aPolyIndex) {
02307             if (meshA.Polys()[aPolyIndex].Plane().SignedDistance(midPointXRay.Origin()) < 0) {
02308                meshB.Polys()[i].Classification()= 1;
02309             } else {
02310                meshB.Polys()[i].Classification()= 2;
02311             }
02312          } else {
02313             meshB.Polys()[i].Classification()= 2;
02314          }
02315       }
02316    }
02317 
02318    //______________________________________________________________________________
02319    template <typename CMesh, typename TMesh>
02320    void extract_classification(CMesh &meshA, TMesh &newMesh, Int_t classification, Bool_t reverse)
02321    {
02322       UInt_t i;
02323       for (i = 0; i < meshA.Polys().size(); ++i) {
02324          typename CMesh::Polygon &meshAPolygon = meshA.Polys()[i];
02325          if (meshAPolygon.Classification() == classification) {
02326             newMesh.Polys().push_back(meshAPolygon);
02327             typename TMesh::Polygon &newPolygon = newMesh.Polys().back();
02328             if (reverse) newPolygon.Reverse();
02329             Int_t j;
02330             for (j=0; j< newPolygon.Size(); j++) {
02331                if (meshA.Verts()[newPolygon[j]].VertexMap() == -1) {
02332                   newMesh.Verts().push_back(meshA.Verts()[newPolygon[j]]);
02333                   meshA.Verts()[newPolygon[j]].VertexMap() = newMesh.Verts().size() -1;
02334                }
02335                newPolygon.VertexProps(j) = meshA.Verts()[newPolygon[j]].VertexMap();
02336             }
02337          }
02338       }
02339    }
02340 
02341    //______________________________________________________________________________
02342    template <typename MeshA, typename MeshB>
02343    void copy_mesh(const MeshA &source, MeshB &output)
02344    {
02345       Int_t vertexNum = source.Verts().size();
02346       Int_t polyNum = source.Polys().size();
02347 
02348       typedef typename MeshB::VLIST VLIST_t;
02349       typedef typename MeshB::PLIST PLIST_t;
02350 
02351       output.Verts() = VLIST_t(vertexNum);
02352       output.Polys() = PLIST_t(polyNum);
02353 
02354       std::copy(source.Verts().begin(), source.Verts().end(), output.Verts().begin());
02355       std::copy(source.Polys().begin(), source.Polys().end(), output.Polys().begin());
02356    }
02357 
02358    //______________________________________________________________________________
02359    void build_tree(const AMesh_t &mesh, TBBoxTree &tree)
02360    {
02361       Int_t numLeaves = mesh.Polys().size();
02362       TBBoxLeaf *aLeaves = new TBBoxLeaf[numLeaves];
02363       UInt_t i;
02364       for (i=0;i< mesh.Polys().size(); i++) {
02365          TPolygonGeometry<AMesh_t> pg(mesh,i);
02366          aLeaves[i] = TBBoxLeaf(i, fit_bbox(pg));
02367       }
02368       tree.BuildTree(aLeaves,numLeaves);
02369    }
02370 
02371    //______________________________________________________________________________
02372    void extract_classification_preserve(const AMesh_t &meshA,
02373                                         const AMesh_t &meshB,
02374                                         const TBBoxTree &aTree,
02375                                         const TBBoxTree &bTree,
02376                                         const OverlapTable_t &aOverlapsB,
02377                                         const OverlapTable_t &bOverlapsA,
02378                                         Int_t aClassification,
02379                                         Int_t bClassification,
02380                                         Bool_t reverseA,
02381                                         Bool_t reverseB,
02382                                         AMesh_t &output)
02383    {
02384       AConnectedMesh_t meshAPartitioned;
02385       AConnectedMesh_t meshBPartitioned;
02386       copy_mesh(meshA,meshAPartitioned);
02387       copy_mesh(meshB,meshBPartitioned);
02388       AConnectedMeshWrapper_t meshAWrapper(meshAPartitioned);
02389       AConnectedMeshWrapper_t meshBWrapper(meshBPartitioned);
02390       meshAWrapper.BuildVertexPolyLists();
02391       meshBWrapper.BuildVertexPolyLists();
02392       partition_mesh(meshAWrapper, meshB, bOverlapsA);
02393       partition_mesh(meshBWrapper, meshA, aOverlapsB);
02394       classify_mesh(meshB, bTree, meshAPartitioned);
02395       classify_mesh(meshA, aTree, meshBPartitioned);
02396       extract_classification(meshAPartitioned, output, aClassification, reverseA);
02397       extract_classification(meshBPartitioned, output, bClassification, reverseB);
02398    }
02399 
02400    //______________________________________________________________________________
02401    void extract_classification(const AMesh_t &meshA,
02402                                const AMesh_t &meshB,
02403                                const TBBoxTree &aTree,
02404                                const TBBoxTree &bTree,
02405                                const OverlapTable_t &aOverlapsB,
02406                                const OverlapTable_t &bOverlapsA,
02407                                Int_t aClassification,
02408                                Int_t bClassification,
02409                                Bool_t reverseA,
02410                                Bool_t reverseB,
02411                                AMesh_t &output)
02412    {
02413       AMesh_t meshAPartitioned(meshA);
02414       AMesh_t meshBPartitioned(meshB);
02415       AMeshWrapper_t meshAWrapper(meshAPartitioned);
02416       AMeshWrapper_t meshBWrapper(meshBPartitioned);
02417       partition_mesh(meshAWrapper, meshB, bOverlapsA);
02418       partition_mesh(meshBWrapper, meshA, aOverlapsB);
02419       classify_mesh(meshB, bTree, meshAPartitioned);
02420       classify_mesh(meshA, aTree, meshBPartitioned);
02421       extract_classification(meshAPartitioned, output, aClassification, reverseA);
02422       extract_classification(meshBPartitioned, output, bClassification, reverseB);
02423    }
02424 
02425    //______________________________________________________________________________
02426    AMesh_t *build_intersection(const AMesh_t &meshA, const AMesh_t &meshB, Bool_t preserve)
02427    {
02428       TBBoxTree aTree, bTree;
02429       build_tree(meshA, aTree);
02430       build_tree(meshB, bTree);
02431       OverlapTable_t bOverlapsA(meshA.Polys().size());
02432       OverlapTable_t aOverlapsB(meshB.Polys().size());
02433       build_split_group(meshA, meshB, aTree, bTree, aOverlapsB, bOverlapsA);
02434       AMesh_t *output = new AMesh_t;
02435       if (preserve) {
02436          extract_classification_preserve(
02437                                          meshA, meshB, aTree, bTree,
02438                                          aOverlapsB, bOverlapsA,
02439                                          1, 1, kFALSE, kFALSE, *output
02440                                         );
02441       } else {
02442          extract_classification(
02443                                 meshA, meshB, aTree, bTree,
02444                                 aOverlapsB, bOverlapsA,
02445                                 1, 1, kFALSE, kFALSE, *output
02446                                );
02447       }
02448       return output;
02449    }
02450 
02451    //______________________________________________________________________________
02452    AMesh_t *build_union(const AMesh_t &meshA, const AMesh_t &meshB, Bool_t preserve)
02453    {
02454       TBBoxTree aTree, bTree;
02455       build_tree(meshA, aTree);
02456       build_tree(meshB, bTree);
02457       OverlapTable_t bOverlapsA(meshA.Polys().size());
02458       OverlapTable_t aOverlapsB(meshB.Polys().size());
02459       build_split_group(meshA, meshB, aTree, bTree, aOverlapsB, bOverlapsA);
02460       AMesh_t *output = new AMesh_t;
02461       if (preserve) {
02462          extract_classification_preserve(
02463                                          meshA, meshB, aTree, bTree,
02464                                          aOverlapsB, bOverlapsA,
02465                                          2, 2, kFALSE, kFALSE, *output
02466                                         );
02467       } else {
02468          extract_classification(
02469                                 meshA, meshB, aTree, bTree,
02470                                 aOverlapsB, bOverlapsA,
02471                                 2, 2, kFALSE, kFALSE, *output
02472                                );
02473       }
02474       return output;
02475    }
02476 
02477    //______________________________________________________________________________
02478    AMesh_t *build_difference(const AMesh_t &meshA, const AMesh_t &meshB, Bool_t preserve)
02479    {
02480       TBBoxTree aTree, bTree;
02481       build_tree(meshA, aTree);
02482       build_tree(meshB, bTree);
02483       OverlapTable_t bOverlapsA(meshA.Polys().size());
02484       OverlapTable_t aOverlapsB(meshB.Polys().size());
02485       build_split_group(meshA, meshB, aTree, bTree, aOverlapsB, bOverlapsA);
02486       AMesh_t *output = new AMesh_t;
02487       if (preserve) {
02488          extract_classification_preserve(
02489                                          meshA, meshB, aTree, bTree,
02490                                          aOverlapsB, bOverlapsA,
02491                                          2, 1, kFALSE, kTRUE, *output
02492                                         );
02493       } else {
02494          extract_classification(
02495                                 meshA, meshB, aTree, bTree,
02496                                 aOverlapsB, bOverlapsA,
02497                                 2, 1, kFALSE, kTRUE, *output
02498                                );
02499       }
02500       return output;
02501    }
02502 
02503    //______________________________________________________________________________
02504    TBaseMesh *ConvertToMesh(const TBuffer3D &buff)
02505    {
02506       AMesh_t *newMesh = new AMesh_t;
02507       const Double_t *v = buff.fPnts;
02508 
02509       newMesh->Verts().resize(buff.NbPnts());
02510 
02511       for (UInt_t i = 0; i < buff.NbPnts(); ++i)
02512          newMesh->Verts()[i] = TVertexBase(v[i * 3], v[i * 3 + 1], v[i * 3 + 2]);
02513 
02514       const Int_t *segs = buff.fSegs;
02515       const Int_t *pols = buff.fPols;
02516 
02517       newMesh->Polys().resize(buff.NbPols());
02518 
02519       for (UInt_t numPol = 0, j = 1; numPol < buff.NbPols(); ++numPol) {
02520          TestPolygon_t &currPoly = newMesh->Polys()[numPol];
02521          Int_t segmentInd = pols[j] + j;
02522          Int_t segmentCol = pols[j];
02523          Int_t s1 = pols[segmentInd];
02524          segmentInd--;
02525          Int_t s2 = pols[segmentInd];
02526          segmentInd--;
02527          Int_t segEnds[] = {segs[s1 * 3 + 1], segs[s1 * 3 + 2],
02528                             segs[s2 * 3 + 1], segs[s2 * 3 + 2]};
02529          Int_t numPnts[3] = {0};
02530 
02531          if (segEnds[0] == segEnds[2]) {
02532             numPnts[0] = segEnds[1], numPnts[1] = segEnds[0], numPnts[2] = segEnds[3];
02533          } else if (segEnds[0] == segEnds[3]) {
02534             numPnts[0] = segEnds[1], numPnts[1] = segEnds[0], numPnts[2] = segEnds[2];
02535          } else if (segEnds[1] == segEnds[2]) {
02536             numPnts[0] = segEnds[0], numPnts[1] = segEnds[1], numPnts[2] = segEnds[3];
02537          } else {
02538             numPnts[0] = segEnds[0], numPnts[1] = segEnds[1], numPnts[2] = segEnds[2];
02539          }
02540 
02541          currPoly.AddProp(TBlenderVProp(numPnts[0]));
02542          currPoly.AddProp(TBlenderVProp(numPnts[1]));
02543          currPoly.AddProp(TBlenderVProp(numPnts[2]));
02544 
02545          Int_t lastAdded = numPnts[2];
02546 
02547          Int_t end = j + 1;
02548          for (; segmentInd != end; segmentInd--) {
02549             segEnds[0] = segs[pols[segmentInd] * 3 + 1];
02550             segEnds[1] = segs[pols[segmentInd] * 3 + 2];
02551             if (segEnds[0] == lastAdded) {
02552                currPoly.AddProp(TBlenderVProp(segEnds[1]));
02553                lastAdded = segEnds[1];
02554             } else {
02555                currPoly.AddProp(TBlenderVProp(segEnds[0]));
02556                lastAdded = segEnds[0];
02557             }
02558          }
02559          j += segmentCol + 2;
02560       }
02561 
02562       AMeshWrapper_t wrap(*newMesh);
02563 
02564       wrap.ComputePlanes();
02565 
02566       return newMesh;
02567    }
02568 
02569    //______________________________________________________________________________
02570    TBaseMesh *BuildUnion(const TBaseMesh *l, const TBaseMesh *r)
02571    {
02572       return build_union(*static_cast<const AMesh_t *>(l), *static_cast<const AMesh_t *>(r), kFALSE);
02573    }
02574 
02575    //______________________________________________________________________________
02576    TBaseMesh *BuildIntersection(const TBaseMesh *l, const TBaseMesh *r)
02577    {
02578       return build_intersection(*static_cast<const AMesh_t *>(l), *static_cast<const AMesh_t *>(r), kFALSE);
02579    }
02580 
02581    //______________________________________________________________________________
02582    TBaseMesh *BuildDifference(const TBaseMesh *l, const TBaseMesh *r)
02583    {
02584       return build_difference(*static_cast<const AMesh_t *>(l), *static_cast<const AMesh_t *>(r), kFALSE);
02585    }
02586 
02587 }

Generated on Tue Jul 5 14:16:57 2011 for ROOT_528-00b_version by  doxygen 1.5.1