contrib/mul/mmn/mmn_make_tri_tree.cxx
Go to the documentation of this file.
00001 #include "mmn_make_tri_tree.h"
00002 //:
00003 // \file
00004 // \brief Compute arcs defining a graph s.t. triangles form a tree.
00005 // \author Tim Cootes
00006 
00007 #include <vcl_cassert.h>
00008 
00009 static void  update_best_arcs(const vnl_matrix<double>& D,
00010                               const vcl_vector<bool>& node_free,
00011                               vcl_vector<mmn_arc>& arcs, unsigned a,
00012                               vcl_vector<unsigned>& best_arc,
00013                               vcl_vector<double>& best_d)
00014 {
00015   unsigned v1=arcs[a].v1;
00016   unsigned v2=arcs[a].v2;
00017   for (unsigned i=0;i<node_free.size();++i)
00018   {
00019     if (node_free[i])
00020     {
00021       double d = D(i,v1)+D(i,v2);
00022       if (d<best_d[i])
00023       {
00024         best_d[i]=d;
00025         best_arc[i]=a;
00026       }
00027     }
00028   }
00029 }
00030 
00031 //: Compute arcs defining a graph s.t. triangles form a tree.
00032 //  Compute arc of graph such that point belongs to at least one triangle,
00033 //  and the graph of triangles is a tree (acyclic).
00034 //  Two triangles are neighbours if they share an edge (arc).
00035 //
00036 //  The approach is to select nodes one at a time, at each step
00037 //  choosing the node closest to two nodes ending an existing arc.
00038 //  This gives two new arcs.
00039 //
00040 //  Complexity is approximately O(n^2)
00041 //
00042 //  \param D: a symmetric matrix indicating proximity of two nodes
00043 //  \param arcs: Output 2n-3 arcs defining the graph.
00044 //  \param v0: If input as < D.rows() then defines one node of the first arc
00045 void mmn_make_tri_tree(const vnl_matrix<double>& D,
00046                        vcl_vector<mmn_arc>& arcs,
00047                        unsigned int v0)
00048 {
00049   unsigned n = D.rows();
00050   assert(D.cols()==n);
00051 
00052   vcl_vector<bool> node_free(n,true);
00053 
00054   // Record of index of best arc for each node
00055   // arcs[best_arc[i]] is arc whose nodes are closest to i
00056   // best_d[i] is the sum of D(i,v1)+D(i,v2)
00057   vcl_vector<unsigned> best_arc(n);
00058   vcl_vector<double> best_d(n);
00059 
00060   arcs.resize(0);
00061 
00062   // Deduce the first arc
00063   mmn_arc arc(0,1);
00064 
00065   if (v0<n)
00066   {
00067     // Find nearest neighbour of v0
00068     double min_d=9e9;
00069     unsigned best_i=n+1;
00070     for (unsigned i=0;i<n;++i)
00071       if (i!=v0)
00072       {
00073         if (best_i>n || D(v0,i)<min_d)
00074         { best_i=i; min_d=D(v0,i); }
00075       }
00076     arc = mmn_arc(v0,best_i);
00077   }
00078   else
00079   {
00080     // Find smallest element in D
00081     double min_d = D(arc.v1,arc.v2);
00082     for (unsigned j=1;j<n;++j)
00083       for (unsigned i=0;i<j;++i)
00084       {
00085         if (D(i,j)<min_d)
00086         {
00087           arc=mmn_arc(i,j); min_d=D(i,j);
00088         }
00089       }
00090   }
00091   arcs.push_back(arc);
00092   node_free[arc.v1]=false;
00093   node_free[arc.v2]=false;
00094 
00095   // Initialise list of best arcs and distances
00096   for (unsigned i=0;i<n;++i)
00097   {
00098     best_arc[i]=0;
00099     if (node_free[i]) best_d[i] = D(i,arc.v1)+D(i,arc.v2);
00100   }
00101 
00102   for (unsigned k=2;k<n;++k)
00103   {
00104     // Search for node with lowest distance to an arc end
00105     double min_d=9e9;
00106     unsigned best_i=n+1;
00107     for (unsigned i=0;i<n;++i)
00108       if (node_free[i])
00109       {
00110         if (best_i>n || best_d[i]<min_d)
00111         { min_d=best_d[i]; best_i=i; }
00112       }
00113 
00114     arc = arcs[best_arc[best_i]];
00115     // Record arcs from node best_i to ends of arc best_arcs[best_i]
00116     node_free[best_i]=false;
00117     arcs.push_back(mmn_arc(best_i,arc.v1));
00118     arcs.push_back(mmn_arc(best_i,arc.v2));
00119 
00120     // Re-evaluate distances to each free point
00121     update_best_arcs(D,node_free,arcs,arcs.size()-2,best_arc,best_d);
00122     update_best_arcs(D,node_free,arcs,arcs.size()-1,best_arc,best_d);
00123   }
00124 }
00125 
00126 //: Compute arcs defining a graph s.t. triangles form a tree.
00127 //  Compute arc of graph such that point belongs to at least one triangle,
00128 //  and the graph of triangles is a tree (acyclic).
00129 //  Two triangles are neighbours if they share an edge (arc).
00130 //
00131 //  The approach is to select nodes one at a time, at each step
00132 //  choosing the node closest to two nodes ending an existing arc.
00133 //  This gives two new arcs.
00134 //
00135 //  Complexity is approximately O(n^2)
00136 //
00137 //  \param D: a symmetric matrix indicating proximity of two nodes
00138 //  \param arcs: Output 2n-3 arcs defining the graph.
00139 //  \param v0: If input as < D.rows() then defines one node of the first arc
00140 void mmn_make_tri_tree(const vnl_matrix<double>& D,
00141                        vcl_vector<mmn_arc>& arcs,
00142                        vcl_vector<mmn_triplet>& triplets,
00143                        vcl_vector<mmn_dependancy>& deps,
00144                        unsigned int v0)
00145 {
00146   unsigned n = D.rows();
00147   assert(D.cols()==n);
00148 
00149   vcl_vector<bool> node_free(n,true);
00150 
00151   // Record of index of best arc for each node
00152   // arcs[best_arc[i]] is arc whose nodes are closest to i
00153   // best_d[i] is the sum of D(i,v1)+D(i,v2)
00154   vcl_vector<unsigned> best_arc(n);
00155   vcl_vector<double> best_d(n);
00156 
00157   arcs.resize(0);
00158   triplets.resize(0);
00159 
00160   vcl_vector<mmn_dependancy> deps0;
00161 
00162   // Deduce the first arc
00163   mmn_arc arc(0,1);
00164 
00165   if (v0<n)
00166   {
00167     // Find nearest neighbour of v0
00168     double min_d=9e9;
00169     unsigned best_i=n+1;
00170     for (unsigned i=0;i<n;++i)
00171       if (i!=v0)
00172       {
00173         if (best_i>n || D(v0,i)<min_d)
00174         { best_i=i; min_d=D(v0,i); }
00175       }
00176     arc = mmn_arc(v0,best_i);
00177   }
00178   else
00179   {
00180     // Find smallest element in D
00181     double min_d = D(arc.v1,arc.v2);
00182     for (unsigned j=1;j<n;++j)
00183       for (unsigned i=0;i<j;++i)
00184       {
00185         if (D(i,j)<min_d)
00186         {
00187           arc=mmn_arc(i,j); min_d=D(i,j);
00188         }
00189       }
00190   }
00191   arcs.push_back(arc);
00192   node_free[arc.v1]=false;
00193   node_free[arc.v2]=false;
00194 
00195   // Create dependency: v1 depends on v2 though arc 0
00196   deps0.push_back(mmn_dependancy(arc.v1,arc.v2, 0));
00197 
00198   // Initialise list of best arcs and distances
00199   for (unsigned i=0;i<n;++i)
00200   {
00201     best_arc[i]=0;
00202     if (node_free[i]) best_d[i] = D(i,arc.v1)+D(i,arc.v2);
00203   }
00204 
00205   for (unsigned k=2;k<n;++k)
00206   {
00207     // Search for node with lowest distance to an arc end
00208     double min_d=9e9;
00209     unsigned best_i=n+1;
00210     for (unsigned i=0;i<n;++i)
00211       if (node_free[i])
00212       {
00213         if (best_i>n || best_d[i]<min_d)
00214         { min_d=best_d[i]; best_i=i; }
00215       }
00216 
00217     arc = arcs[best_arc[best_i]];
00218     // Record arcs from node best_i to ends of arc best_arcs[best_i]
00219     node_free[best_i]=false;
00220 
00221     unsigned ai=arcs.size();  // For index
00222     arcs.push_back(mmn_arc(best_i,arc.v1));
00223     arcs.push_back(mmn_arc(best_i,arc.v2));
00224 
00225     unsigned ti=triplets.size();
00226     triplets.push_back(mmn_triplet(best_i,arc.v1,arc.v2));
00227 
00228     // best_i depends on arc.v1 and arc.v2 through 3 arcs and a triplet
00229     deps0.push_back(mmn_dependancy(best_i,arc.v1,arc.v2,
00230                                   ai,ai+1, best_arc[best_i], ti));
00231 
00232     // Re-evaluate distances to each free point
00233     update_best_arcs(D,node_free,arcs,ai,  best_arc,best_d);
00234     update_best_arcs(D,node_free,arcs,ai+1,best_arc,best_d);
00235   }
00236 
00237   // Reverse the order of the dependancies, so last is processed first
00238   unsigned n_deps=deps0.size();
00239   deps.resize(n_deps);
00240   for (unsigned i=0;i<n_deps;++i)
00241     deps[i]=deps0[n_deps-1-i];
00242 }
00243