Open
Graph Drawing
Framework

 v.2012.05
 

NMM.h
Go to the documentation of this file.
00001 /*
00002  * $Revision: 2299 $
00003  * 
00004  * last checkin:
00005  *   $Author: gutwenger $ 
00006  *   $Date: 2012-05-07 15:57:08 +0200 (Mon, 07 May 2012) $ 
00007  ***************************************************************/
00008  
00043 #ifdef _MSC_VER
00044 #pragma once
00045 #endif
00046 
00047 #ifndef OGDF_NMM_H
00048 #define OGDF_NMM_H
00049 
00050 #include <ogdf/basic/Graph.h>
00051 #include <ogdf/basic/List.h>
00052 #include <ogdf/basic/Array2D.h>
00053 #include <ogdf/basic/geometry.h>
00054 #include <ogdf/internal/energybased/NodeAttributes.h>
00055 #include <ogdf/internal/energybased/EdgeAttributes.h>
00056 #include <ogdf/internal/energybased/QuadTreeNM.h>
00057 #include <ogdf/internal/energybased/ParticleInfo.h>
00058 #include <ogdf/internal/energybased/FruchtermanReingold.h>
00059 #include <complex>
00060 
00061 namespace ogdf {
00062 
00063 class OGDF_EXPORT NMM 
00064 {
00065    
00066    
00067    public:
00068       NMM();          //constructor
00069       ~NMM();         //destructor
00070 
00071       //Calculate rep. forces for each node.
00072       void calculate_repulsive_forces(const Graph &G,NodeArray<NodeAttributes>& A,
00073                                       NodeArray<DPoint>& F_rep);
00074 
00075       //Make all initialisations that are needed for New Multipole Method (NMM)
00076       void make_initialisations (const Graph &G, double boxlength,
00077                  DPoint down_left_corner,int particles_in_leaves,
00078                  int precision,int tree_construction_way,
00079                  int find_small_cell);
00080 
00081       //Dynamically allocated memory is freed here.
00082       void deallocate_memory();
00083 
00084       //Import updated information of the drawing area.
00085       void update_boxlength_and_cornercoordinate(double b_l,DPoint d_l_c);
00086         
00087    private:
00088 
00089        int MIN_NODE_NUMBER; //The minimum number of nodes for which the forces are
00090                             //calculated using NMM (for lower values the exact 
00091                             //calculation is used).
00092        bool using_NMM; //Indicates whether the exact method or NMM is used for force
00093                        //calculation (value depends on MIN_NODE_NUMBER)
00094        FruchtermanReingold ExactMethod; //needed in case that using_NMM == false
00095  
00096        int _tree_construction_way;//1 = pathwise;2 = subtreewise
00097        int _find_small_cell;//0 = iterative; 1= Aluru
00098        int _particles_in_leaves;//max. number of particles for leaves of the quadtree
00099        int _precision;  //precision for p-term multipole expansion
00100     
00101        double boxlength;//length of drawing box
00102        DPoint down_left_corner;//down left corner of drawing box
00103 
00104        int* power_of_2;//holds the powers of 2 (for speed reasons to calculate the
00105                        //maximal boxindex (index is from 0 to max_power_of_2_index)
00106        int max_power_of_2_index;//holds max. index for power_of_2 (= 30) 
00107        double ** BK; //holds the binomial coefficients
00108        List<DPoint> rep_forces;   //stores the rep. forces of the last iteration 
00109                                   //(needed for error calculation)
00110 
00111       //private helping functions
00112 
00113       //The array power_of_2 is calculated for values from 0 to max_power_of_2_index
00114       //which is set here to 30.
00115       void init_power_of_2_array(void);
00116 
00117       //The space of power_of_2 is freed.
00118       void free_power_of_2_array();     
00119 
00120       //Returns power_of_2[i] for values <= max_power_of_2_index else it returns 
00121       //pow(2,i).
00122       int power_of_two(int i);  
00123     
00124       //Returns the maximal index of a box in level i.
00125       int maxboxindex (int level);
00126 
00127       //Use NMM for force calculation (used for large Graphs (|V| > MIN_NODE_NUMBER)).
00128       void  calculate_repulsive_forces_by_NMM(const Graph &G, NodeArray 
00129                   <NodeAttributes>& A ,NodeArray<DPoint>& F_rep);
00130                     
00131       //Use the exact method for force calculation (used for small Graphs (|V| <=
00132       //MIN_NODE_NUMBER) for speed reasons).
00133       void  calculate_repulsive_forces_by_exact_method(const Graph &G, NodeArray 
00134                   <NodeAttributes>& A ,NodeArray<DPoint>& F_rep);
00135 
00136       // *********Functions needed for path by path tree construction***********
00137    
00138       //The reduced quadtree is build up path by path (the Lists LE,ME, the
00139       //centers, D1, D2, M, and quad_tree_leaves are not calculated here.
00140       void  build_up_red_quad_tree_path_by_path(const Graph& G, NodeArray
00141                            <NodeAttributes>& A,QuadTreeNM& T);
00142 
00143       //Makes L_x(y)_copy a copy of L_x(y)_orig and sets p.copy_item for each element in 
00144       //L_x(y)_orig to the ListIterator of the corresponding element in L_x(y)_copy;
00145       //Furthermore, the p.cross_ref_items in L_x(y)_copy are set and p.subList_ptr and
00146       //p.tmp_cross_ref_item is reset to NULL in both lists.
00147       void make_copy_and_init_Lists(List<ParticleInfo>& L_x_orig,List<ParticleInfo>& 
00148                    L_x_copy,List<ParticleInfo>& L_y_orig,List
00149                    <ParticleInfo>& L_y_copy);
00150 
00151       //The root node of T is constructed.
00152       void build_up_root_node(const Graph& G,NodeArray<NodeAttributes>& A,QuadTreeNM& T);
00153 
00154       //The sorted and linked Lists L_x and L_y for the root node are created.
00155       void create_sorted_coordinate_Lists(const Graph& G,NodeArray<NodeAttributes>& A, 
00156                    List<ParticleInfo>& L_x,List<ParticleInfo>& L_y);
00157 
00158       //T is extended by a subtree T1 rooted at the T.get_act_node().  
00159       //The boxlength and down_left_corner of the actual node is reduced if it is
00160       //not the minimal subquad that contains all the particles in the represented area.
00161       void  decompose_subtreenode(QuadTreeNM& T,List<ParticleInfo>& act_x_List_copy,
00162                   List<ParticleInfo>& act_y_List_copy,List<QuadTreeNodeNM*>& 
00163                   new_leaf_List);
00164 
00165       //The extreme coordinates of the particles contained in *act_ptr are calculated.
00166       void calculate_boundaries_of_act_node(QuadTreeNodeNM* act_ptr,double& x_min,
00167                        double& x_max,double& y_min,double& y_max);
00168 
00169       //Returns true if the rectangle defined by x_min,...,y_max lies within the
00170       //left(right)_top(bottom) quad of the small cell of *act_ptr.
00171       bool in_lt_quad(QuadTreeNodeNM* act_ptr,double x_min,double x_max, double y_min,
00172               double y_max);
00173       bool in_rt_quad(QuadTreeNodeNM* act_ptr,double x_min,double x_max, double y_min,
00174               double y_max);
00175       bool in_lb_quad(QuadTreeNodeNM* act_ptr,double x_min,double x_max, double y_min,
00176               double y_max);
00177       bool in_rb_quad(QuadTreeNodeNM* act_ptr,double x_min,double x_max, double y_min,
00178               double y_max);
00179 
00180     //The Lists *act_ptr->get_x(y)_List_ptr() are split into two sublists containing
00181     //the particles in the left and right half of the actual quad. The list that is 
00182     //larger is constructed from *act_ptr->get_x(y)_List_ptr() by deleting the other
00183     //elements; The smaller List stays empty at this point, but the corresponding
00184     //elements in L_x(y)_copy contain a pointer to the x(y) List, where they belong to.
00185     void split_in_x_direction(
00186         QuadTreeNodeNM* act_ptr,
00187         List<ParticleInfo>*& L_x_left_ptr,
00188         List<ParticleInfo>*& L_y_left_ptr,
00189         List<ParticleInfo>*& L_x_right_ptr,
00190         List <ParticleInfo>*& L_y_right_ptr);
00191       
00192     //The Lists *act_ptr->get_x(y)_List_ptr() are split into two subLists containing
00193     //the particles in the top /bottom half ...
00194     void split_in_y_direction(
00195         QuadTreeNodeNM* act_ptr,
00196         List<ParticleInfo>*& L_x_bottom_ptr,
00197         List<ParticleInfo>*& L_y_bottom_ptr,
00198         List<ParticleInfo>*& L_x_top_ptr,
00199         List<ParticleInfo>*& L_y_top_ptr);
00200       
00201       
00202     //The Lists *L_x(y)_left_ptr are constructed from *act_ptr->get_x(y)_List_ptr()
00203     //by deleting all elements right from last_left_item in *act_ptr->get_x_List_ptr()
00204     //the corresponding values in  *act_ptr->get_y_List_ptr() are deleted as well.
00205     //The corresponding List-elements of the deleted elements in the Lists L_x(y)_copy
00206     //hold the information, that they belong to the Lists *L_x(y)_left_ptr.
00207     void x_delete_right_subLists(
00208         QuadTreeNodeNM* act_ptr,
00209         List<ParticleInfo>*& L_x_left_ptr,
00210         List <ParticleInfo>*& L_y_left_ptr,
00211         List<ParticleInfo>*& L_x_right_ptr,
00212         List <ParticleInfo>*& L_y_right_ptr,
00213         ListIterator<ParticleInfo> last_left_item);
00214       
00215     //Analogue as above.
00216     void x_delete_left_subLists(
00217         QuadTreeNodeNM* act_ptr,
00218         List<ParticleInfo>*& L_x_left_ptr,
00219         List <ParticleInfo>*& L_y_left_ptr,
00220         List<ParticleInfo>*& L_x_right_ptr,
00221         List <ParticleInfo>*& L_y_right_ptr,
00222         ListIterator<ParticleInfo> last_left_item); 
00223       
00224     //The Lists *L_x(y)_left_ptr are constructed from *act_ptr->get_x(y)_List_ptr()
00225     //by deleting all elements right from last_left_item in *act_ptr->get_y_List_ptr()
00226     //the ... 
00227     void y_delete_right_subLists(
00228         QuadTreeNodeNM* act_ptr,
00229         List<ParticleInfo>*& L_x_left_ptr,
00230         List<ParticleInfo>*& L_y_left_ptr,
00231         List<ParticleInfo>*& L_x_right_ptr,
00232         List <ParticleInfo>*& L_y_right_ptr,
00233         ListIterator<ParticleInfo> last_left_item);
00234       
00235     //Analogue as above.
00236     void y_delete_left_subLists(
00237         QuadTreeNodeNM* act_ptr,
00238         List<ParticleInfo>*& L_x_left_ptr,
00239         List<ParticleInfo>*& L_y_left_ptr,
00240         List<ParticleInfo>*& L_x_right_ptr,
00241         List <ParticleInfo>*& L_y_right_ptr,
00242         ListIterator<ParticleInfo> last_left_item); 
00243       
00244       
00245     //The Lists *L_x(y)_b_ptr and *L_x(y)_t_ptr are constructed from the Lists 
00246     // *L_x(y)_ptr.
00247     void split_in_y_direction(
00248         QuadTreeNodeNM* act_ptr,
00249         List<ParticleInfo>*& L_x_ptr,
00250         List<ParticleInfo>*& L_x_b_ptr,
00251         List<ParticleInfo>*& L_x_t_ptr,
00252         List<ParticleInfo>*& L_y_ptr,
00253         List<ParticleInfo>*& L_y_b_ptr,
00254         List<ParticleInfo>*& L_y_t_ptr);
00255       
00256       //The Lists *L_x(y)_b(t)_ptr are constructed from the Lists *L_x(y)_ptr by 
00257       //moving all List elements from *L_x(y)_ptr that belong to *L_x(y)_l_ptr 
00258       //to this List. the L_x(y)_right_ptr point  to the reduced Lists L_x(y)_ptr 
00259       //afterwards.      
00260       void y_move_left_subLists(List<ParticleInfo>*& L_x_ptr,List<ParticleInfo>*& 
00261                 L_x_b_ptr,List<ParticleInfo>*& L_x_t_ptr,List
00262                 <ParticleInfo>*& L_y_ptr,List <ParticleInfo>*& 
00263                 L_y_b_ptr,List<ParticleInfo>*& 
00264                 L_y_t_ptr,ListIterator<ParticleInfo> last_left_item);
00265       
00266       //Same as above but the elements that belong to *&L_x(y)_right_ptr are moved.
00267       void y_move_right_subLists(List<ParticleInfo>*& L_x_ptr,List<ParticleInfo>*&
00268                  L_x_b_ptr,List<ParticleInfo>*& L_x_t_ptr,List
00269                  <ParticleInfo>*&L_y_ptr,List <ParticleInfo>*& 
00270                  L_y_b_ptr,List<ParticleInfo>*& 
00271                  L_y_t_ptr,ListIterator<ParticleInfo> last_left_item);
00272       
00273       //The sorted subLists, that can be accesssed by the entries in L_x(y)_copy->
00274       //get_subList_ptr() are constructed.
00275       void build_up_sorted_subLists(List<ParticleInfo>& L_x_copy,List<ParticleInfo>&
00276                     act_y_List_copy);   
00277      
00278       // ************functions needed for subtree by subtree tree construction **********
00279      
00280       //The reduced quadtree is build up subtree by subtree (the lists LE, ME the
00281       //centers, D1, D2, M, quad_tree_leaves are not calculated here.
00282       void  build_up_red_quad_tree_subtree_by_subtree(const Graph& G, NodeArray
00283                               <NodeAttributes>& A,QuadTreeNM& T);
00284      
00285       //The root node of T is constructed and contained_nodes is set to the list of
00286       //all nodes of G.
00287       void build_up_root_vertex(const Graph&G,QuadTreeNM& T);
00288       
00289       //The reduced subtree of T rooted at *subtree_root_ptr containing all the particles
00290       //of subtree_root_ptr->get_contained_nodes() is constructed; Pointers to leaves 
00291       //of the subtree that contain more than particles_in_leaves() particles in their
00292       //contained_nodes() lists are added to new_subtree_root_List_ptr; The lists 
00293       //contained_nodes() are nonempty only for the (actual) leaves of T.
00294       void construct_subtree(NodeArray<NodeAttributes>& A,QuadTreeNM& T,QuadTreeNodeNM* 
00295                  subtree_root_ptr,List<QuadTreeNodeNM*>& 
00296                  new_subtree_root_List);
00297       
00298       //A complete subtree of T and of depth subtree_depth, rooted at *T.get_act_ptr() is
00299       //constructed. Furthermore leaf_ptr[i][j] points to a leaf node of the subtree
00300       //that represents the quadratic subregion of *T.get_act_ptr() at subtree_depth
00301       //and position [i][j] i,j in 0,...,maxindex;act_depth(x_index,y_index) are
00302       //helping variables for recursive calls.
00303       void construct_complete_subtree(QuadTreeNM& T,int subtree_depth,
00304                       Array2D<QuadTreeNodeNM*>& leaf_ptr,
00305                       int act_depth,int 
00306                       act_x_index,int act_y_index);
00307       
00308       //The particles in subtree_root_ptr->get_contained_nodes() are assigned to 
00309       //the the contained_nodes lists of the leaves of the subtree by using the 
00310       //information of A,leaf_ptr and maxindex. Afterwards contained_nodes of 
00311       // *subtree_root_ptr is empty.
00312       void set_contained_nodes_for_leaves(NodeArray<NodeAttributes>& A,
00313                       QuadTreeNodeNM* subtree_root_ptr,Array2D
00314                       <QuadTreeNodeNM*>& leaf_ptr,int  maxindex);
00315       
00316       //The subtree of T rooted at *T.get_act_ptr() is traversed bottom up, such that
00317       //the subtreeparticlenumber of every node in this subtree is set correctly.
00318       void set_particlenumber_in_subtree_entries(QuadTreeNM& T);
00319       
00320       //The reduced subtree rooted at *T.get_act_ptr() is calculated ; A pointer to 
00321       //every leaf of this subtree that contains more then particles_in_leaves() 
00322       //particles is added to new_subtree_root_List; The lists contained_nodes are 
00323       //empty for all but the leaves.
00324       void construct_reduced_subtree(NodeArray<NodeAttributes>& A,QuadTreeNM& T,List
00325                      <QuadTreeNodeNM*>& new_subtree_root_List);
00326       
00327       //All subtrees of *T.get_act_ptr() that have a child c of *T.get_act_ptr() as root
00328       //and c.get_particlenumber_in_subtree() == 0 are deleted.
00329       void delete_empty_subtrees(QuadTreeNM& T);
00330       
00331       //If *T.get_act_ptr() is a degenerated node (has only one child c) *T.get_act_ptr()
00332       //is deleted from T and the child c is linked with the father of *T.get_act_ptr()
00333       //if *T.get_act_ptr() is the root of T than c is set to the new root of T
00334       //T.get_act_ptr() points to c afterwards; Furthermore true is returned if
00335       // *T.get_act_ptr() has been degenerated, else false is returned.
00336       bool check_and_delete_degenerated_node(QuadTreeNM& T);
00337       
00338       //The subtree rooted at new_leaf_ptr is deleted, *new_leaf_ptr is a leaf 
00339       //of T and new_leaf_ptr->get_contained_nodes() contains all the particles
00340       //contained in the leaves of the deleted subtree; Precondition: T.get_act_ptr() is
00341       //new_leaf_ptr.
00342       void delete_sparse_subtree(QuadTreeNM& T,QuadTreeNodeNM* new_leaf_ptr);
00343       
00344       //new_leaf_ptr->get_contained_nodes() contains all the particles contained in
00345       //the leaves of its subtree afterwards; Precondition: T.get_act_ptr() is
00346       //new_leaf_ptr
00347       void collect_contained_nodes(QuadTreeNM& T,QuadTreeNodeNM* new_leaf_ptr);
00348       
00349       //If all nodes in T.get_act_ptr()->get_contained_nodes() have the same position
00350       //false is returned. Else true is returned and
00351       //the boxlength, down_left_corner and level of *T.get_act_ptr() is updated
00352       //such that this values are minimal (i.e. the smallest quad that contains all
00353       //the particles of T.get_act_ptr()->get_contained_nodes(); If all this particles
00354       //are placed at a point nothing is done.
00355       bool find_smallest_quad(NodeArray<NodeAttributes>& A,QuadTreeNM& T);
00356       
00357       // *********functions needed for subtree by subtree tree construction(end) ********
00358       
00359       //Finds the small cell of the actual Node of T iteratively,and updates 
00360       //Sm_downleftcorner, Sm_boxlength, and level of *act_ptr. 
00361       void find_small_cell_iteratively(QuadTreeNodeNM* act_ptr,double x_min,double x_max,
00362                        double y_min,double y_max);
00363       
00364       //Finds the small cell of the actual Node of T by Aluru's Formula, and updates
00365       //Sm_downleftcorner, Sm_boxlength, and level of *act_ptr. 
00366       void find_small_cell_by_formula(QuadTreeNodeNM* act_ptr,double x_min,double x_max,
00367                       double y_min,double y_max);
00368       
00369       //The reduced quad tree is deleted; Furthermore the treenode_number is calculated.
00370       void delete_red_quad_tree_and_count_treenodes(QuadTreeNM& T);
00371       
00372       //The multipole expansion terms ME are calculated for all nodes of T ( centers are
00373       //initialized for each cell and quad_tree_leaves stores pointers to leaves of T).
00374       void form_multipole_expansions(NodeArray<NodeAttributes>& A,QuadTreeNM& T,List
00375                      <QuadTreeNodeNM*>& quad_tree_leaves);
00376       
00377       //The multipole expansion List ME for the tree rooted at T.get_act_ptr() is
00378       //recursively calculated. 
00379       void form_multipole_expansion_of_subtree(NodeArray<NodeAttributes>& A,QuadTreeNM& 
00380                            T, List<QuadTreeNodeNM*>& 
00381                            quad_tree_leaves);
00382       
00383       //The Lists ME and LE are both initialized to zero entries for *act_ptr.
00384       void init_expansion_Lists(QuadTreeNodeNM* act_ptr);
00385       
00386       //The center of the box of *act_ptr is initialized.  
00387       void set_center(QuadTreeNodeNM* act_ptr);
00388       
00389       //Calculate List ME for *act_ptr Precondition: *act_ptr is a leaf.
00390       void form_multipole_expansion_of_leaf_node(NodeArray<NodeAttributes>& A,
00391                           QuadTreeNodeNM* act_ptr);
00392       
00393       //Add the shifted ME Lists of *act_ptr to act_ptr->get_father_ptr() ; precondition
00394       // *act_ptr has a father_node.
00395       void add_shifted_expansion_to_father_expansion(QuadTreeNodeNM* act_ptr);
00396       
00397       //According to NMM T is traversed recursively top-down starting from act_node_ptr 
00398       //== T.get_root_ptr() and thereby the lists D1, D2, M and LE are calculated for all
00399       //treenodes. 
00400       void calculate_local_expansions_and_WSPRLS(NodeArray<NodeAttributes>&A,
00401                          QuadTreeNodeNM* act_node_ptr);
00402       
00403       //If the small cell of ptr_1 and ptr_2 are well separated true is returned (else
00404       //false).
00405       bool well_separated(QuadTreeNodeNM* ptr_1,QuadTreeNodeNM* ptr_2);
00406       
00407       //If ptr_1 and ptr_2 are nonequal and bordering true is returned; else false.
00408       bool bordering(QuadTreeNodeNM* ptr_1,QuadTreeNodeNM* ptr_2);
00409       
00410       //The shifted local expansion of the father of node_ptr is added to the local
00411       //expansion of node_ptr;precondition: node_ptr is not the root of T.
00412       void add_shifted_local_exp_of_parent(QuadTreeNodeNM* node_ptr);  
00413       
00414       //The multipole expansion of *ptr_1 is transformed into a local expansion around
00415       //the center of *ptr_2 and added to *ptr_2 s local expansion list.
00416       void add_local_expansion(QuadTreeNodeNM* ptr_1,QuadTreeNodeNM* ptr_2);
00417       
00418       //The multipole expansion for every particle of leaf_ptr->contained_nodes 
00419       //(1,0,...) is transformed into a local expansion around the center of *ptr_2 and 
00420       //added to *ptr_2 s local expansion List;precondition: *leaf_ptr is a leaf.
00421       void add_local_expansion_of_leaf(NodeArray<NodeAttributes>&A,QuadTreeNodeNM*
00422                     leaf_ptr,QuadTreeNodeNM* act_ptr);
00423       
00424       //For each leaf v in quad_tree_leaves the force contribution defined by 
00425       //v.get_local_exp() is calculated and stored in F_local_exp.
00426       void transform_local_exp_to_forces(NodeArray <NodeAttributes>&A, 
00427                      List<QuadTreeNodeNM*>& quad_tree_leaves,
00428                      NodeArray<DPoint>& F_local_exp);
00429       
00430       //For each leaf v in quad_tree_leaves the force contribution defined by all nodes
00431       //in v.get_M() is calculated and stored in F_multipole_exp.
00432       void transform_multipole_exp_to_forces(NodeArray<NodeAttributes>& A,
00433                          List<QuadTreeNodeNM*>& quad_tree_leaves, 
00434                          NodeArray<DPoint>& F_multipole_exp);
00435       
00436       //For each leaf v in quad_tree_leaves the force contributions from all leaves in
00437       //v.get_D1() and v.get_D2() are calculated.
00438       void calculate_neighbourcell_forces(NodeArray<NodeAttributes>& 
00439                       A,List<QuadTreeNodeNM*>& quad_tree_leaves,
00440                       NodeArray<DPoint>& F_direct);
00441       
00442       //Add repulsive force contributions for each node.
00443       void add_rep_forces(const Graph& G,NodeArray<DPoint>& F_direct,NodeArray<DPoint>& 
00444               F_multipole_exp,NodeArray<DPoint>& F_local_exp,
00445               NodeArray<DPoint>& F_rep);
00446       
00447       //Returns the repulsing force_function_value of scalar d. 
00448       double f_rep_scalar (double d);
00449       
00450       //Init BK -matrix for values n, k in 0 to t.
00451       void init_binko(int t);    
00452       
00453       //Free space for BK.
00454       void free_binko();
00455       
00456       //Returns n over k.
00457       double binko(int n, int k);
00458       
00459       //The way to construct the reduced tree (0) = level by level (1) path by path 
00460       //(2) subtree by subtree
00461       int tree_construction_way() const {return _tree_construction_way;}
00462       void tree_construction_way(int a) { _tree_construction_way= 
00463                         (((0<=a)&&(a<=2)) ? a : 0);}
00464       
00465       //(0) means that the smallest quadratic cell that surrounds a node of the 
00466       //quadtree is calculated iteratively in constant time (1) means that it is 
00467       //calculated by the formula of Aluru et al. in constant time
00468       int find_sm_cell() const {return _find_small_cell;}
00469       void find_sm_cell(int a) { _find_small_cell = 
00470                    (((0<=a)&&(a<=1)) ? a : 0);}    
00471       
00472       //Max. number of particles that are contained in a leaf of the red. quadtree.
00473       void particles_in_leaves (int b) { _particles_in_leaves = ((b>= 1)? b : 1);}
00474       int particles_in_leaves () const { return _particles_in_leaves;}  
00475       
00476       //The precision p for the p-term multipole expansions.
00477       void precision (int p) { _precision  = ((p >= 1 ) ? p : 1);}
00478       int  precision () const {return _precision;}
00479       
00480 };
00481 }//namespace ogdf
00482 #endif
00483 
00484