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