1 #include "mmn_make_tri_tree.h"
2 //:
3 // \file
4 // \brief Compute arcs defining a graph s.t. triangles form a tree.
5 // \author Tim Cootes
6 
7 #include <cassert>
8 #ifdef _MSC_VER
9 #  include "vcl_msvc_warnings.h"
10 #endif
11 
update_best_arcs(const vnl_matrix<double> & D,const std::vector<bool> & node_free,std::vector<mmn_arc> & arcs,unsigned a,std::vector<unsigned> & best_arc,std::vector<double> & best_d)12 static void  update_best_arcs(const vnl_matrix<double>& D,
13                               const std::vector<bool>& node_free,
14                               std::vector<mmn_arc>& arcs, unsigned a,
15                               std::vector<unsigned>& best_arc,
16                               std::vector<double>& best_d)
17 {
18   unsigned v1=arcs[a].v1;
19   unsigned v2=arcs[a].v2;
20   for (unsigned i=0;i<node_free.size();++i)
21   {
22     if (node_free[i])
23     {
24       double d = D(i,v1)+D(i,v2);
25       if (d<best_d[i])
26       {
27         best_d[i]=d;
28         best_arc[i]=a;
29       }
30     }
31   }
32 }
33 
34 //: Compute arcs defining a graph s.t. triangles form a tree.
35 //  Compute arc of graph such that point belongs to at least one triangle,
36 //  and the graph of triangles is a tree (acyclic).
37 //  Two triangles are neighbours if they share an edge (arc).
38 //
39 //  The approach is to select nodes one at a time, at each step
40 //  choosing the node closest to two nodes ending an existing arc.
41 //  This gives two new arcs.
42 //
43 //  Complexity is approximately O(n^2)
44 //
45 //  \param D: a symmetric matrix indicating proximity of two nodes
46 //  \param arcs: Output 2n-3 arcs defining the graph.
47 //  \param v0: If input as < D.rows() then defines one node of the first arc
mmn_make_tri_tree(const vnl_matrix<double> & D,std::vector<mmn_arc> & arcs,unsigned int v0)48 void mmn_make_tri_tree(const vnl_matrix<double>& D,
49                        std::vector<mmn_arc>& arcs,
50                        unsigned int v0)
51 {
52   unsigned n = D.rows();
53   assert(D.cols()==n);
54 
55   std::vector<bool> node_free(n,true);
56 
57   // Record of index of best arc for each node
58   // arcs[best_arc[i]] is arc whose nodes are closest to i
59   // best_d[i] is the sum of D(i,v1)+D(i,v2)
60   std::vector<unsigned> best_arc(n);
61   std::vector<double> best_d(n);
62 
63   arcs.resize(0);
64 
65   // Deduce the first arc
66   mmn_arc arc(0,1);
67 
68   if (v0<n)
69   {
70     // Find nearest neighbour of v0
71     double min_d=9e9;
72     unsigned best_i=n+1;
73     for (unsigned i=0;i<n;++i)
74       if (i!=v0)
75       {
76         if (best_i>n || D(v0,i)<min_d)
77         { best_i=i; min_d=D(v0,i); }
78       }
79     arc = mmn_arc(v0,best_i);
80   }
81   else
82   {
83     // Find smallest element in D
84     double min_d = D(arc.v1,arc.v2);
85     for (unsigned j=1;j<n;++j)
86       for (unsigned i=0;i<j;++i)
87       {
88         if (D(i,j)<min_d)
89         {
90           arc=mmn_arc(i,j); min_d=D(i,j);
91         }
92       }
93   }
94   arcs.push_back(arc);
95   node_free[arc.v1]=false;
96   node_free[arc.v2]=false;
97 
98   // Initialise list of best arcs and distances
99   for (unsigned i=0;i<n;++i)
100   {
101     best_arc[i]=0;
102     if (node_free[i]) best_d[i] = D(i,arc.v1)+D(i,arc.v2);
103   }
104 
105   for (unsigned k=2;k<n;++k)
106   {
107     // Search for node with lowest distance to an arc end
108     double min_d=9e9;
109     unsigned best_i=n+1;
110     for (unsigned i=0;i<n;++i)
111       if (node_free[i])
112       {
113         if (best_i>n || best_d[i]<min_d)
114         { min_d=best_d[i]; best_i=i; }
115       }
116 
117     arc = arcs[best_arc[best_i]];
118     // Record arcs from node best_i to ends of arc best_arcs[best_i]
119     node_free[best_i]=false;
120     arcs.emplace_back(best_i,arc.v1);
121     arcs.emplace_back(best_i,arc.v2);
122 
123     // Re-evaluate distances to each free point
124     update_best_arcs(D,node_free,arcs,arcs.size()-2,best_arc,best_d);
125     update_best_arcs(D,node_free,arcs,arcs.size()-1,best_arc,best_d);
126   }
127 }
128 
129 //: Compute arcs defining a graph s.t. triangles form a tree.
130 //  Compute arc of graph such that point belongs to at least one triangle,
131 //  and the graph of triangles is a tree (acyclic).
132 //  Two triangles are neighbours if they share an edge (arc).
133 //
134 //  The approach is to select nodes one at a time, at each step
135 //  choosing the node closest to two nodes ending an existing arc.
136 //  This gives two new arcs.
137 //
138 //  Complexity is approximately O(n^2)
139 //
140 //  \param D: a symmetric matrix indicating proximity of two nodes
141 //  \param arcs: Output 2n-3 arcs defining the graph.
142 //  \param v0: If input as < D.rows() then defines one node of the first arc
mmn_make_tri_tree(const vnl_matrix<double> & D,std::vector<mmn_arc> & arcs,std::vector<mmn_triplet> & triplets,std::vector<mmn_dependancy> & deps,unsigned int v0)143 void mmn_make_tri_tree(const vnl_matrix<double>& D,
144                        std::vector<mmn_arc>& arcs,
145                        std::vector<mmn_triplet>& triplets,
146                        std::vector<mmn_dependancy>& deps,
147                        unsigned int v0)
148 {
149   unsigned n = D.rows();
150   assert(D.cols()==n);
151 
152   std::vector<bool> node_free(n,true);
153 
154   // Record of index of best arc for each node
155   // arcs[best_arc[i]] is arc whose nodes are closest to i
156   // best_d[i] is the sum of D(i,v1)+D(i,v2)
157   std::vector<unsigned> best_arc(n);
158   std::vector<double> best_d(n);
159 
160   arcs.resize(0);
161   triplets.resize(0);
162 
163   std::vector<mmn_dependancy> deps0;
164 
165   // Deduce the first arc
166   mmn_arc arc(0,1);
167 
168   if (v0<n)
169   {
170     // Find nearest neighbour of v0
171     double min_d=9e9;
172     unsigned best_i=n+1;
173     for (unsigned i=0;i<n;++i)
174       if (i!=v0)
175       {
176         if (best_i>n || D(v0,i)<min_d)
177         { best_i=i; min_d=D(v0,i); }
178       }
179     arc = mmn_arc(v0,best_i);
180   }
181   else
182   {
183     // Find smallest element in D
184     double min_d = D(arc.v1,arc.v2);
185     for (unsigned j=1;j<n;++j)
186       for (unsigned i=0;i<j;++i)
187       {
188         if (D(i,j)<min_d)
189         {
190           arc=mmn_arc(i,j); min_d=D(i,j);
191         }
192       }
193   }
194   arcs.push_back(arc);
195   node_free[arc.v1]=false;
196   node_free[arc.v2]=false;
197 
198   // Create dependency: v1 depends on v2 though arc 0
199   deps0.emplace_back(arc.v1,arc.v2, 0);
200 
201   // Initialise list of best arcs and distances
202   for (unsigned i=0;i<n;++i)
203   {
204     best_arc[i]=0;
205     if (node_free[i]) best_d[i] = D(i,arc.v1)+D(i,arc.v2);
206   }
207 
208   for (unsigned k=2;k<n;++k)
209   {
210     // Search for node with lowest distance to an arc end
211     double min_d=9e9;
212     unsigned best_i=n+1;
213     for (unsigned i=0;i<n;++i)
214       if (node_free[i])
215       {
216         if (best_i>n || best_d[i]<min_d)
217         { min_d=best_d[i]; best_i=i; }
218       }
219 
220     arc = arcs[best_arc[best_i]];
221     // Record arcs from node best_i to ends of arc best_arcs[best_i]
222     node_free[best_i]=false;
223 
224     unsigned ai=arcs.size();  // For index
225     arcs.emplace_back(best_i,arc.v1);
226     arcs.emplace_back(best_i,arc.v2);
227 
228     unsigned ti=triplets.size();
229     triplets.emplace_back(best_i,arc.v1,arc.v2);
230 
231     // best_i depends on arc.v1 and arc.v2 through 3 arcs and a triplet
232     deps0.emplace_back(best_i,arc.v1,arc.v2,
233                                   ai,ai+1, best_arc[best_i], ti);
234 
235     // Re-evaluate distances to each free point
236     update_best_arcs(D,node_free,arcs,ai,  best_arc,best_d);
237     update_best_arcs(D,node_free,arcs,ai+1,best_arc,best_d);
238   }
239 
240   // Reverse the order of the dependancies, so last is processed first
241   unsigned n_deps=deps0.size();
242   deps.resize(n_deps);
243   for (unsigned i=0;i<n_deps;++i)
244     deps[i]=deps0[n_deps-1-i];
245 }
246