reducedSurface.h

Go to the documentation of this file.
00001 // -*- Mode: C++; tab-width: 2; -*-
00002 // vi: set ts=2:
00003 //
00004 
00005 #ifndef BALL_STRUCTURE_REDUCEDSURFACE_H
00006 #define BALL_STRUCTURE_REDUCEDSURFACE_H
00007 
00008 #ifndef BALL_MATHC_COMMON_H
00009 # include <BALL/MATHS/common.h>
00010 #endif
00011 
00012 #ifndef BALL_MATHS_SIMPLEBOX3_H
00013 # include <BALL/MATHS/simpleBox3.h>
00014 #endif
00015 
00016 #ifndef BALL_MATHS_CIRCLE3_H
00017 # include <BALL/MATHS/circle3.h>
00018 #endif
00019 
00020 #ifndef BALL_MATHS_SPHERE_H
00021 # include <BALL/MATHS/sphere3.h>
00022 #endif
00023 
00024 #ifndef BALL_MATHS_VECTOR3_H
00025 # include <BALL/MATHS/vector3.h>
00026 #endif
00027 
00028 #ifndef BALL_DATATYPE_HASHSET_H
00029 # include <BALL/DATATYPE/hashMap.h>
00030 #endif
00031 
00032 #ifndef BALL_DATATYPE_HASHSET_H
00033 # include <BALL/DATATYPE/hashSet.h>
00034 #endif
00035 
00036 #ifndef BALL_COMMON_EXCEPTION_H
00037 # include <BALL/COMMON/exception.h>
00038 #endif
00039 
00040 #ifndef BALL_STRUCTURE_RSEDGE_H
00041 # include <BALL/STRUCTURE/RSEdge.h>
00042 #endif
00043 
00044 #ifndef BALL_STRUCTURE_RSFACE_H
00045 # include <BALL/STRUCTURE/RSFace.h>
00046 #endif
00047 
00048 #ifndef BALL_STRUCTURE_RSVERTEX_H
00049 # include <BALL/STRUCTURE/RSVertex.h>
00050 #endif
00051 
00052 #include <list>
00053 #include <vector>
00054 
00055 namespace BALL
00056 {
00057   class RSComputer;
00058   class SolventExcludedSurface;
00059   class SESComputer;
00060   class SESSingularityCleaner;
00061   class TriangulatedSES;
00062   class SolventAccessibleSurface;
00063   class TriangulatedSAS;
00064   class SESTriangulator;
00065 
00069   class BALL_EXPORT ReducedSurface
00070   {
00071     public:
00072 
00085     friend class RSComputer;
00086     friend class SolventExcludedSurface;
00087     friend class SESComputer;
00088     friend class SESSingularityCleaner;
00089     friend class SolventAccessibleSurface;
00090     friend class TriangulatedSES;
00091     friend class TriangulatedSAS;
00092     friend class SESTriangulator;
00093 
00094     BALL_CREATE(ReducedSurface)
00095 
00096     
00099 
00104     ReducedSurface();
00105 
00110     ReducedSurface(const ReducedSurface& reduced_surface, bool = true);
00111 
00115     ReducedSurface(const std::vector< TSphere3<double> >& spheres,
00116                    const double& probe_radius);
00117 
00120     virtual ~ReducedSurface();
00121 
00123 
00126 
00130     void operator = (const ReducedSurface& reduced_surface);
00131 
00135     void set(const ReducedSurface& reduced_surface);
00136 
00139     void clear();
00140 
00143     void clean();
00144 
00146 
00149 
00153     Size numberOfAtoms() const;
00154 
00158     Size numberOfVertices() const;
00159 
00163     Size numberOfEdges() const;
00164 
00168     Size numberOfFaces() const;
00169 
00173     double getProbeRadius() const;
00174 
00179     TSphere3<double> getSphere(Position i) const
00180       throw(Exception::IndexOverflow);
00181 
00186     RSVertex* getVertex(Position i) const
00187       throw(Exception::IndexOverflow);
00188 
00193     RSEdge* getEdge(Position i) const
00194       throw(Exception::IndexOverflow);
00195 
00200     RSFace* getFace(Position i) const
00201       throw(Exception::IndexOverflow);
00202 
00206     void insert(RSVertex* rsvertex);
00207 
00211     void insert(RSEdge* rsedge);
00212 
00216     void insert(RSFace* rsface);
00217 
00221     double getMaximalRadius() const;
00222 
00226     TSimpleBox3<double> getBoundingBox() const;
00227 
00232     void deleteSimilarFaces(RSFace* face1, RSFace* face2);
00233 
00242     bool getAngle(RSFace*   face1,   RSFace*   face2,
00243                   RSVertex* vertex1, RSVertex* vertex2,
00244                   TAngle<double>& angle, bool check = false) const;
00245 
00248     void compute()
00249       throw(Exception::GeneralException,
00250             Exception::DivisionByZero,
00251             Exception::IndexOverflow);
00252 
00254 
00255     private:
00256 
00257     /*_ Test whether a ReducedSurface object can be copied.
00258     */
00259     bool canBeCopied(const ReducedSurface& reduced_surface);
00260 
00261     /*_ Copy a ReducedSurface object.
00262     */
00263     void copy(const ReducedSurface& reduced_surface);
00264 
00265     /*_
00266     */
00267     void correctEdges(RSFace* face1, RSFace* face2,
00268                       RSEdge* edge1, RSEdge* edge2);
00269 
00270     /*_
00271     */
00272     void joinVertices(RSFace*   face1,   RSFace*   face2,
00273                       RSVertex* vertex1, RSVertex* vertex2);
00274 
00275     /*_
00276     */
00277     void findSimilarVertices(RSFace* face1, RSFace* face2,
00278                              std::vector<RSVertex*>& rsvertex1,
00279                              std::vector<RSVertex*>& rsvertex2);
00280 
00281     /*_
00282     */
00283     void findSimilarEdges(RSFace* face1, RSFace* face2,
00284                           std::vector<RSEdge*>& rsedge1,
00285                           std::vector<RSEdge*>& rsedge2);
00286 
00287     protected:
00288 
00289     /*_ the number of atoms of the reduced surface
00290     */
00291     Size number_of_atoms_;
00292 
00293     /*_ the atoms of the molecule
00294     */
00295 
00296     std::vector< TSphere3<double> > atom_;
00297 
00298     /*_ probe radius
00299     */
00300     double probe_radius_;
00301 
00302     /*_ the number of vertices of the reduced surface
00303     */
00304     Size number_of_vertices_;
00305 
00306     /*_ the vertices of the reduced surface
00307     */
00308     std::vector< RSVertex* > vertices_;
00309 
00310     /*_ the number of edges of the reduced surface
00311     */
00312     Size number_of_edges_;
00313 
00314     /*_ the edges of the reduced surface
00315     */
00316     std::vector< RSEdge* > edges_;
00317 
00318     /*_ the number of faces of the reduced surface
00319     */
00320     Size number_of_faces_;
00321 
00322     /*_ the faces of the reduced surface
00323     */
00324     std::vector< RSFace* > faces_;
00325 
00326     /*_ maximal radius of all atoms
00327     */
00328     double r_max_;
00329 
00330     /*_ bounding SimpleBox of the atom centers of the molecule
00331     */
00332     TSimpleBox3<double> bounding_box_;
00333   };
00334 
00338 
00342   BALL_EXPORT std::ostream& operator << (std::ostream& s, const ReducedSurface& rs);
00343 
00345 
00349   class BALL_EXPORT RSComputer
00350   {
00351     public:
00352 
00353     BALL_CREATE(RSComputer)
00354 
00355     
00358 
00364     enum ProbeStatus
00365     {
00366       STATUS_OK = 0,
00367       STATUS_NOT_OK,
00368       STATUS_NOT_TESTED
00369     };
00370 
00376     enum AtomStatus
00377     {
00378       STATUS_ON_SURFACE = 0,
00379       STATUS_INSIDE,
00380       STATUS_UNKNOWN
00381     };
00383 
00384     struct ProbePosition
00385     {
00386       ProbeStatus status[2];
00387       TVector3<double> point[2];
00388     };
00389 
00393 
00398     RSComputer();
00399 
00402     RSComputer(ReducedSurface* rs);
00403 
00406     virtual ~RSComputer();
00407 
00409 
00412 
00415     void run()
00416       throw(Exception::GeneralException,
00417             Exception::DivisionByZero,
00418             Exception::IndexOverflow);
00419 
00421 
00422 
00423     private:
00424 
00425     /*_ @name Computing reduced surface
00426     */
00428 
00429     /*_
00430     */
00431     void preProcessing();
00432 
00433     /*_ Compute a RSComponent.
00434     */
00435     void getRSComponent()
00436       throw(Exception::GeneralException,
00437             Exception::DivisionByZero,
00438             Exception::IndexOverflow);
00439 
00440     /*_ Treat all edges of a face.
00441       @param  face  the RSFace to be treated
00442     */
00443     bool treatFace(RSFace* face)
00444       throw(Exception::GeneralException,
00445             Exception::DivisionByZero,
00446             Exception::IndexOverflow);
00447 
00448     /*_ Roll over an edge that belongs to only one face and find the other one.
00449         @param  edge  the RSEdge to be treated
00450     */
00451     bool treatEdge(RSEdge* edge)
00452       throw(Exception::GeneralException,
00453             Exception::DivisionByZero,
00454             Exception::IndexOverflow);
00455 
00456     /*_ Treat an ambiguous situation.
00457         All vertices on an ambiguous atom are deleted with all its edges and
00458         faces. The radius of the atom is decreased by 10 EPSILON.
00459         @param  atom  the index of the atom
00460     */
00461     void correct(Index atom);
00462 
00463     /*_ Check all new created vertices for extensions
00464     */
00465     void extendComponent()
00466       throw(Exception::GeneralException,
00467             Exception::DivisionByZero,
00468             Exception::IndexOverflow);
00469 
00470     /*_ Find a third atom rolling over two vertices starting on a face.
00471         From all atoms which can be touched by the probe sphere when it
00472         touches the given two vertices we choose the one with smallest
00473         rotation angle.
00474         If the rotation angle equals zero, the probe sphere can touch four
00475         atoms and an exception is thrown.
00476         If no atom can be found an exception is thrown.
00477       @param  vertex1 the first vertex
00478       @param  vertex2 the second vertex
00479       @param  face    the starting face
00480       @param  probe   the new probe sphere
00481       @param  phi     the rotation angle
00482       @return Index   index of the found atom
00483     */
00484     Index thirdAtom(RSVertex* vertex1, RSVertex* vertex2,
00485                     RSFace* face, TSphere3<double>& probe, TAngle<double>& phi)
00486       throw(Exception::GeneralException,
00487             Exception::DivisionByZero,
00488             Exception::IndexOverflow);
00489 
00491     /*_ @name Finding a start position
00492     */
00494 
00495     /*_ Find a start position
00496       @param  vertex    a pointer to the found vertex, if only a vertex
00497                         can be found
00498       @param  edge      a pointer to the found edge, if only an edge can be
00499                         found
00500       @param  face      a pointer to the found face, if a face can be found
00501       @return Position  0, if no start position is found,
00502                         1, if a single vertex is found,
00503                         2, if an edge is found,
00504                         3, if a face is found
00505     */
00506     Position getStartPosition()
00507       throw(Exception::DivisionByZero);
00508 
00510     /*_ @name Finding a first face
00511     */
00513 
00514     /*_ Try to find a starting face
00515       @return RSFace* a pointer to the found face, if a face can be found,
00516                           NULL otherwise
00517     */
00518     RSFace* findFirstFace()
00519       throw(Exception::DivisionByZero);
00520 
00521     /*_ Try to find a starting face in a given direction
00522       @param  direction   search in x-direction, if direction is 0,
00523                           search in y-direction, if direction is 1,
00524                           search in z-direction, if direction is 2
00525       @param  extrem      search in min direction, if extrem is 0,
00526                           search in max direction, if extrem is 1
00527       @return RSFace* a pointer to the found face, if a face can be found,
00528                           NULL otherwise
00529     */
00530     RSFace* findFace(Position direction, Position extrem)
00531       throw(Exception::DivisionByZero);
00532 
00534     /*_ @name Finding a first edge
00535     */
00537 
00538     /*_ Try to find a starting edge
00539       @return RSEdge* a pointer to the found edge, if a face can be found,
00540                           NULL otherwise
00541     */
00542     RSEdge* findFirstEdge();
00543 
00544     /*_ Try to find a starting edge in a given direction
00545       @param  direction   search in x-direction, if direction is 0,
00546                           search in y-direction, if direction is 1,
00547                           search in z-direction, if direction is 2
00548       @param  extrem      search in min direction, if extrem is 0,
00549                           search in max direction, if extrem is 1
00550       @return RSEdge* a pointer to the found edge, if a face can be found,
00551                           NULL otherwise
00552     */
00553     RSEdge* findEdge(Position direction, Position extrem);
00554 
00556     /*_ @name Finding a first vertex
00557     */
00559 
00560     /*_ Try to find a single atom
00561       @return RSVertex* a pointer to the found vertex, if a vertex can be
00562                             found, NULL otherwise
00563     */
00564     RSVertex* findFirstVertex();
00565 
00566     /*_ Find a single atom in a given direction
00567       @param  direction search in x-direction, if direction is 0,
00568                         search in y-direction, if direction is 1,
00569                         search in z-direction, if direction is 2
00570       @param  extrem    search in min direction, if extrem is 0,
00571                         search in max direction, if extrem is 1
00572       @return Index     the index of the found atom
00573     */
00574     Index findFirstAtom(Position direction, Position extrem);
00575 
00576     /*_ Find a second atom close enougth to the first atom in a given direction
00577       @param  atom1     the index of the first atom
00578       @param  direction search in x-direction, if direction is 0,
00579                         search in y-direction, if direction is 1,
00580                         search in z-direction, if direction is 2
00581       @param  extrem    search in min direction, if extrem is 0,
00582                         search in max direction, if extrem is 1
00583       @return Index     the index of the found atom
00584     */
00585     Index findSecondAtom(Index atom, Position direction, Position extrem);
00586 
00587     /*_ Find a second atom close enougth to the first two atoms
00588       @param  atom1     the index of the first atom
00589       @param  atom2     the index of the second atom
00590       @param  atom_list a HashSet of the indices of all candidate atoms
00591       @return ::std::list< ::std::pair< Index,TSphere3<double> > >
00592                         a list of all candidates with their probe spheres
00593     */
00594     void findThirdAtom(Index atom1, Index atom2, const std::list<Index>& third,
00595                        std::list< std::pair< Index,TSphere3<double> > >& atoms);
00596 
00598     /*_ @name Some utilities
00599     */
00601 
00602     /*_ Find all atoms close enougth to two given atoms.
00603       The indices of all atoms which can be touched by the probe sphere when
00604       it touches the given atoms are computed.
00605       @param  atom1       the index of the first given atom
00606       @param  atom2       the index of the second given atom
00607       @param  output_list list of all atoms close enougth to the given atoms
00608     */
00609     void neighboursOfTwoAtoms(Index atom1, Index atom2);
00610 
00611     /*_ Find all atoms close enougth to three given atoms.
00612       The indices of all atoms which can be touched by the probe sphere when
00613       it touches the given atoms are computed.
00614       @param  atom1       the index of the first given atom
00615       @param  atom2       the index of the second given atom
00616       @param  atom3       the index of the third given atom
00617       @param  output_list list of all atoms close enougth to the given atoms
00618     */
00619     void neighboursOfThreeAtoms(Index atom1, Index atom2, Index atom3,
00620                                 std::list<Index>& output_list);
00621 
00622     /*_ Get the extrem coordinate of a circle in a given direction
00623       @param  circle    the circle
00624       @param  direction search in x-direction, if direction is 0,
00625                         search in y-direction, if direction is 1,
00626                         search in z-direction, if direction is 2
00627       @param  extrem    search in min direction, if extrem is 0,
00628                         search in max direction, if extrem is 1
00629       @return double          the extrem coordinate
00630     */
00631     double getCircleExtremum(const TCircle3<double>& circle,
00632                              Position direction, Position extrem);
00633 
00635     /*_ @name Creating / updating edges / faces
00636     */
00638 
00639     /*_ Create a free edge from two vertices if it is a free edge
00640       @param  vertex1     a pointer to the first vertex
00641       @param  vertex2     a pointer to the second vertex
00642       @return RSEdge* a pointer to the created free edge, if there is one,
00643                           NULL otherwise
00644     */
00645     RSEdge* createFreeEdge(RSVertex* vertex1, RSVertex* vertex2);
00646 
00647     /*_ Get the circle described by the center of the probe sphere and the two
00648         contact circles with the atoms when the probe sphere rolls over two
00649         atoms
00650         @param  atom1   the index of the first atom
00651         @param  atom2   the index of the second atom
00652         @param  circle1 the circle described by the center of the probe sphere
00653         @param  circle2 the contact circle with atom1
00654         @param  circle3 the contact circle with atom2
00655         @return bool    true, if the probe sphere can touch both atoms,
00656                         false, otherwise
00657     */
00658     bool getCircles(Index atom1, Index atom2, TCircle3<double>& circle1,
00659                     TCircle3<double>& circle2, TCircle3<double>& circle3);
00660 
00661     /*_ Get the normal vector of the face described by three atoms and a probe
00662       @param  atom1       the index of the first atom
00663       @param  atom2       the index of the second atom
00664       @param  atom3       the index of the third atom
00665       @param  probe       the probe sphere lying on atom1, atom2, atom3
00666       @return TVector3<double>  the normal vector
00667     */
00668     TVector3<double> getFaceNormal(const TSphere3<double>& atom1, const TSphere3<double>& atom2,
00669                                    const TSphere3<double>& atom3, const TSphere3<double>& probe);
00670 
00671     /*_ Update a face and it's edges
00672       @param  v1    the first vertex of the face
00673       @param  v2    the second vertex of the face
00674       @param  v3    the third vertex of the face
00675       @param  e1    the first edge
00676       @param  e2    the second edge
00677       @param  e3    the third edge
00678       @param  f     the face
00679       @param  probe the probe sphere of the face
00680     */
00681     void updateFaceAndEdges(RSVertex* v1, RSVertex* v2, RSVertex* v3,
00682                             RSEdge*   e1, RSEdge*   e2, RSEdge*   e3,
00683                             RSFace* f, const TSphere3<double>& probe);
00684 
00685     /*_ Test, whether a face exists or not
00686       @param  face        a pointer to the face to be tested
00687       @return RSFace* a pointer to the face, if it exists, otherwise NULL
00688     */
00689     RSFace* faceExists(RSFace* face, const std::list< RSVertex* >& vertices);
00690 
00692     /*_ @name Finding a probe sphere
00693     */
00695 
00696     /*_ Get the centers of the probe sphere when it lies on three atoms
00697       @param  a1    the first atom
00698       @param  a2    the second atom
00699       @param  a3    the third atom
00700       @param  c1    the first center
00701       @param  c2    the second center
00702       @return bool  true, if the probe sphere can touch the three atoms,
00703                     false, otherwise
00704     */
00705     bool centerOfProbe(Index a1, Index a2, Index a3,
00706                        TVector3<double>& c1, TVector3<double>& c2);
00707 
00708     /*_ Check,weather a probe sphere is inside an atom
00709       @param  probe the probe sphere to be tested
00710       @return bool  true, if the probe sphere is not intersecting any atom
00711                     false, otherwise
00712     */
00713     bool checkProbe(const TSphere3<double>& probe,
00714                     Index atom1, Index atom2, Index atom3);
00715 
00716     /*_
00717     */
00718     void correctProbePosition(Position atom);
00719 
00720     /*_
00721     */
00722     void sort(Index  u1, Index  u2, Index  u3,
00723               Index& s1, Index& s2, Index& s3);
00724 
00725     /*_
00726     */
00727     void correctProbePosition(Position a1, Position a2, Position a3);
00728 
00729     /*_
00730     */
00731     void insert(RSVertex* vertex);
00732 
00733     /*_
00734     */
00735     void insert(RSEdge* edge);
00736 
00737     /*_
00738     */
00739     void insert(RSFace* face);
00740 
00742 
00743     protected:
00744 
00745     /*_ a pointer to the reduced surface to compute
00746     */
00747     ReducedSurface* rs_;
00748 
00749     /*_ for each atom a list of its neighbours
00750     */
00751     std::vector< std::list<Index> > neighbours_;
00752 
00753     /*_ for each atom a status
00754     */
00755     std::vector< AtomStatus > atom_status_;
00756 
00757     /*_ for each pair of atoms a list of its neighbours
00758     */
00759     HashMap< Position, HashMap< Position, std::list<Index> > > neighbours_of_two_;
00760 
00761     /*_ for each triple of atoms its probe positions
00762     */
00763     HashMap< Position, 
00764              HashMap< Position, HashMap< Position, ProbePosition* > > > probe_positions_;
00765 
00766     /*_ all new created vertices which are not yet checked for extensions
00767     */
00768     HashSet<RSVertex*> new_vertices_;
00769 
00770     /*_ all new created faces which are not completely treated yet
00771     */
00772     HashSet<RSFace*> new_faces_;
00773 
00774     /*_ for each atom a list of the rsvertices of the atom
00775     */
00776     std::vector< std::list<RSVertex*> > vertices_;
00777   };
00778 } // namespace BALL
00779 
00780 #endif  // BALL_STRUCTURE_REDUCEDSURFACE_H