cheshirekow  v0.1.0
Triangulation.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012 Josh Bialkowski (jbialk@mit.edu)
3  *
4  * This file is part of mpblocks.
5  *
6  * mpblocks is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * mpblocks is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with mpblocks. If not, see <http://www.gnu.org/licenses/>.
18  */
27 #ifndef MPBLOCKS_CLARKSON93_DYNAMIC_TRIANGULATION_HPP_
28 #define MPBLOCKS_CLARKSON93_DYNAMIC_TRIANGULATION_HPP_
29 
30 #include <mpblocks/clarkson93.hpp>
31 
32 namespace mpblocks {
33 namespace clarkson93 {
34 namespace dynamic {
35 
36 
37 
38 template <class Traits>
40  m_xv_walked( simplex::XVISIBLE_WALK ),
41  m_x_visible( simplex::XVISIBLE ),
42  m_xv_queue( simplex::XVISIBLE_QUEUED )
43 {
44  m_ndim = 0;
45  clear();
46 }
47 
48 
49 template <class Traits>
51 {
52  clear();
53 }
54 
55 template <class Traits>
57 {
58  m_antiOrigin = setup.antiOrigin();
59  m_deref = setup.deref();
60  m_ndim = setup.ndim();
61 
62  m_x_visible .reserve( setup.xVisiblePrealloc() );
63  m_xv_queue .reserve( setup.xVisiblePrealloc() );
64  m_xv_walked .reserve( setup.xVisiblePrealloc() );
65  m_xv_walk .reserve( setup.xVisiblePrealloc() );
66 
67  m_ridges. reserve( setup.horizonPrealloc() );
68 
69  setup.setupAlloc( m_sAlloc );
70 }
71 
72 template <class Traits>
73 template <class Iterator>
75  Iterator begin, Iterator end)
76 {
77  // just some convenient storage for the initial simplices
78  std::vector<Simplex*> S(m_ndim+1);
79 
80  // then, if we have enough for the first simplex, we need to build it
81  int i=0;
82  Simplex* S_0 = m_sAlloc.create();
83  for( Iterator ipRef = begin; ipRef != end; ++ipRef )
84  {
85  S_0->vertices[i++] = ipRef;
86  }
87  S_0->calculateConstraint( m_ndim, m_deref );
88  S_0->orientConstraint( m_deref( S_0->vertices[0] ),
90 
91 
92  // we also need to setup all of the infinite simplices
93  for(int i=0; i < m_ndim+1; i++)
94  {
95  S[i] = m_sAlloc.create();
96  S[i]->vertices[0] = m_antiOrigin;
97  S[i]->neighbors[0] = S_0;
98 // S[i]->inv[0] = i;
99  S_0->neighbors[i] = S[i];
100 // S_0->inv[i] = 0;
101 
102  for(int j=0; j < m_ndim+1; j++)
103  {
104  int k=j;
105  if( j < i )
106  k++;
107  else if( j==i )
108  continue;
109 
110  S[i]->vertices[k] = S_0->vertices[j];
111  }
112 
113  // we can't use the peak vertex of the inifinite simplices to
114  // orient them, because it is fictious, so we'll orient it toward
115  S[i]->calculateConstraint( m_ndim, m_deref );
116  S[i]->orientConstraint( m_deref(S_0->vertices[i]),
118  }
119 
120  // now we need to assign neighbors
121  for(int i=0; i < m_ndim+1; i++)
122  {
123  // the i'th Simplex, S[i], shares all vertices with S_0 except for
124  // S_0's i'th vertex. Also if q is a vertex of S[i] and of S_0, then
125  // the neighbor of S_0 opposite q is also the neighbor of S[i]
126  // opposite q... I think. I should probably work that out and
127  // make sure
128 
129  // S[i]'s j'th neighbor is
130  // S_0 if j = 0
131  // S[j-1] if j <= i
132  // S[j] if j > i
133  // thus the inverse mapping is found by
134  // S[i].N[j] = S[k]
135  // S[k].N[x] =
136  // S_0 if x = 0
137  // S[x-1] if x <= k
138  // => x-1 = i
139  // => x = i+1
140  // => i+1 <= k
141  // => i <= k-1
142  // S[x] if x > k
143  // => x = i
144  // => i > k
145  // thus:
146  // if( i <= k-1 )
147  // S[k].N[i+1] = S[i]
148  // else
149  // S[k].N[i] = S[i]
150  //
151  // for example, in 3d:
152  // i = 0, j = 1 => k = 1
153  // S[0].N[1] = S[1]
154  // 0 <= 1-1 so i <= k-1 so x=i+1=1 and
155  // S[1].N[1] = S[0]
156  // i =0, j = 2 => k = 2
157  // S[0].N[2] = S[2]
158  // 0 <= 2-1 so i <= k-1 so x=i+1=1 and
159  // s[2].N[1] = S[0]
160  for(int j=1; j < m_ndim+1; j++)
161  {
162  int k = (j <= i ) ? j-1 : j;
163  S[i]->neighbors[j] = S[k];
164 // if( i < k-1 )
165 // S[i]->inv[j] = i+1;
166 // else
167 // S[i]->inv[j] = i;
168  }
169  }
170 
171  m_origin = S_0;
172  m_hullSimplex = S[0];
173 }
174 
175 
176 template <class Traits>
178 {
179  find_x_visible(x,S);
180  alter_x_visible(x);
181 }
182 
183 
184 
185 template <class Traits>
187 {
188  m_hullSimplex = 0;
189  m_origin = 0;
190  m_sAlloc.clear();
191 }
192 
193 template <class Traits>
195 {
196  // first clear out our search structures
197  // so the flags get reset, we do this at the beginning so that after the
198  // the update they persist and we can view them for debugging
199  m_xv_walk.clear();
200  m_xv_walked.clear();
201 
202  m_x_visible.clear();
203  m_xv_queue.clear();
204 
205 // brute force search for x_visible and infinite
206 // for( Simplex* S = m_sAlloc.m_start; S != m_sAlloc.m_next; ++S)
207 // {
208 // if( S->isVisible( m_deref(x) ) && S->isInfinite( m_antiOrigin ) )
209 // m_x_visible.push(S);
210 // }
211 
212 
213  // if we were not given a starting point start at the origin
214  if( !S )
215  S = m_origin;
216 
217  // if the origin simplex is not visible then start at the neighbor
218  // across his base, which must be x-visible
219  if( !S->isVisible( m_deref(x) ) )
220  S = S->neighbors[0];
221 
222  // sanity check
223  assert( S->isVisible( m_deref(x) ) );
224 
225  // star the search at S
226  m_xv_walked.push( S );
227  m_xv_walk.push( PQ_Key( 0, S ) );
228 
229  // clear out S
230  S = 0;
231 
232  // starting at the given simplex, walk in the direction of x until
233  // we find an x-visible infinite simplex (i.e. hull facet)
234  while( m_xv_walk.size() > 0 )
235  {
236  Simplex* pop = m_xv_walk.pop().val;
237 
238  // at each step queue all x-visible simplices sorted by origin
239  // distance to x
240  for(int i=1; i < m_ndim+1; i++)
241  {
242  Simplex* N = pop->neighbors[i];
243 
244  if( N->isVisible( m_deref(x) )
245  && !m_xv_walked.isMember(N) )
246  {
247  // if N is x-visible and infinite then we are done
248  if(N->isInfinite(m_antiOrigin) )
249  {
250  S = N;
251  break;
252  }
253 
254  // otherwise add N to the search queue
255  Scalar d =
256  ( m_deref(x) - m_deref(N->vertices[0]) ).squaredNorm();
257  m_xv_walked.push(N);
258  m_xv_walk.push( PQ_Key(d,N) );
259  }
260  }
261  }
262 
263  if( !S )
264  return;
265 
266  // at this S is both x-visible and infinite, so we do an expansive
267  // search for all such Simplicies, so we initialize the search stack with
268  // this simplex
269  m_xv_queue.push(S);
270 
271  // at each iteration...
272  while( m_xv_queue.size() > 0 )
273  {
274  // pop one simplex off the stack
275  Simplex* S = m_xv_queue.pop();
276 
277  // add add it to the x_visible set
278  m_x_visible.push(S);
279 
280  // and check all of it's neighbors
281  for( int i=1; i < m_ndim+1; i++ )
282  {
283  // if the neighbor is both infinite and x-visible add it to the
284  // queue, but don't add it to the queue if it's already determined
285  // to be x-visible
286  Simplex* N = S->neighbors[i];
287  if( N->isVisible( m_deref(x) )
288  && N->isInfinite( m_antiOrigin )
289  && !m_x_visible.isMember( N )
290  && !m_xv_queue.isMember( N ) )
291  {
292  m_xv_queue.push( N );
293  }
294  }
295  }
296 
297 
298  /*
299  // start at the origin simplex, and the neighbor sharing it's base
300  // facet
301  if( !S )
302  S = m_origin;
303  m_x_visible_queue.push_back(S);
304  m_x_visible_queue.push_back(S->neighbors[0]);
305 
306  // @todo: there's no reason to keep the whole queue once we get to an
307  // infinite simplex. Instead, do a direct line walk through the
308  // triangulation toward the point x until we get to an infinite
309  // simplex. Then enumerate all infinite and x-visible simplices.
310 
311  // enter the dragon... I mean loop
312  while(m_x_visible_queue.size() > 0)
313  {
314  // read the next simplex that needs expansion, remove it from
315  // the search queue
316  Simplex* simplex = m_x_visible_queue.pop();
317 
318  // if it's already been expanded just continue
319  if( m_x_visible_expanded.isMember(simplex) )
320  continue;
321 
322  // otherwise, we'll expand it so add it to the set
323  m_x_visible_expanded.push(simplex);
324 
325  // check to see if the base facet of this simplex is x-visible,
326  // i.e. x is in the same halfspace divided by the base facet as
327  // the the rest of the simplex
328  if( simplex->isVisible( m_deref(x) ) )
329  {
330  // if it's also an infinite simplex then add it to the list
331  // we're buliding
332  if( simplex->isInfinite(m_antiOrigin) )
333  m_x_visible.push(simplex);
334 
335  // if the base facet is x-visible, then we need to
336  // add all of it's neighbors (except for the neighbor
337  // across the base facet, from whom we entered this
338  // simplex) to the search queue
339  for(int i=1; i < m_ndim+1; i++)
340  {
341  if( !m_x_visible_queue.isMember( simplex->neighbors[i] )
342  && !m_x_visible_expanded.isMember( simplex->neighbors[i] ) )
343  {
344  m_x_visible_queue.push( simplex->neighbors[i] );
345  }
346  }
347  }
348  }
349  */
350 
351 }
352 
353 
354 
355 template <class Traits>
357 {
358  // clear out our list of horizon ridges
359  m_ridges.clear();
360 
361  // first we go through all the x-visible simplices, and replace their
362  // peak vertex (the ficitious anti-origin) with the new point x.
363  size_t nVisible = m_x_visible.size();
364  for(size_t i=0; i < nVisible; ++i)
365  {
366  Simplex* S = m_x_visible[i];
367  S->vertices[0] = x;
368  }
369 
370  // now we have to find the set of horizon ridges, to do this we
371  // find the set of simplices in m_x_visible who have a non base facet G
372  // that emits a neighbor who is not in m_x_visible. The intersection of
373  // G with the base facet of the simplex in m_x_visible is a horizon
374  // ridge
375  for(size_t i=0; i < nVisible; ++i)
376  {
377  Simplex* S = m_x_visible[i];
378 
379  // note that we skip index 0, because we are looking for a
380  // non-base facet
381  for(int i=1; i < m_ndim+1; i++)
382  {
383  // if the the neighbor is not in x-visible then we have found
384  // a non-base facet of this simplex which emits a neighbor
385  // which is not in m_x_visible, and so we have found a
386  // horizon ridge
387  if( !m_x_visible.isMember( S->neighbors[i] ) )
388  {
389  m_ridges.push(S,i);
390  // note that we can't quit, we have to keep searching,
391  // there may be more than one horizon ridge
392  }
393  }
394  }
395 
396  // now for each horizon ridge we have to construct a new simplex
397  size_t nHorizon = m_ridges.size();
398  for( size_t i=0; i < nHorizon; i++ )
399  {
400  HorizonRidge_t& ridge = m_ridges[i];
401 
402  // allocate a new simplex and add it to the list
403  Simplex* simplex = m_sAlloc.create();
404  ridge.generatedSimplex = simplex;
405 
406  // In the parlance of Clarkson, we have two simplices V and N
407  // note that V is ridge->simplex and N is neighbor
408  // ridge->simplex->neighbors[i]. V was an infinite simplex and became
409  // a finite one... and N is still an infinite simplex
410  Simplex* V = ridge.simplex;
411  Simplex* N = V->neighbors[ridge.iExcluded];
412 
413  // the new simplex has a peak vertex at the anti-origin, across from
414  // that vertex is V. Furthermore, V->neighbors[ridge.iExcluded] will
415  // move to point to the new simplex
416  simplex->vertices[0] = m_antiOrigin;
417  simplex->neighbors[0] = V;
418 // simplex->inv[0] = ridge.iExcluded;
419 
420  // note that the neighbor of V opposite it's peak has already been
421  // set, in
422  // fact the only neighbor that needs to be set is the neighbor
423  // across from iExclude which will be the new simplex, so lets
424  // set these guys now, for simplicity, we'll use the same index
425  // in the new simplex
426  simplex->vertices[ridge.iExcluded] = x;
427  simplex->neighbors[ridge.iExcluded] = N;
428 // simplex->inv[ridge.iExcluded] = V->inv[ridge.iExcluded];
429 
430  // before we assign V's iExcluded neighbor to the new simplex,
431  // we need to also assign THAT simplex's neighbor to
432  // this new simplex
433  {
434  // so we scan the neighbors of i to find the index which is
435  // V, and once we find that index, we set that neighbor to the
436  // new simplex
437  // @todo replace this loop with V->inv[ridge.iExcluded]
438  for(int i=0; i < m_ndim+1; i++)
439  {
440  if( N->neighbors[i] == V )
441  {
442  N->neighbors[i] = simplex;
443 // N->inv[i] = ridge.iExcluded;
444  break;
445  }
446  }
447  }
448 
449  V->neighbors[ridge.iExcluded] = simplex;
450 // V-> inv[ridge.iExcluded] = 0;
451 
452  // otherwise it shares all non-base vertices with that of the
453  // simplex which generated this horizon ridge (excluding the
454  // one whose index we recorded )
455  for(int i = 1; i < m_ndim+1; i++)
456  {
457  // if this is the index of the excluded vertex, then we've
458  // already done the work so move on
459  if( i == ridge.iExcluded )
460  continue;
461 
462  // otherwise we copy the vertex from the originating
463  // simplex
464  else
465  {
466  simplex->vertices[i] = V->vertices[i];
467  // note that we'll set the new simplices neighbors in
468  // another loop
469  }
470  }
471 
472  // we'll need to use the half-space inequality at some point but
473  // we can't calcualte it normally b/c one of the vertices isn't at
474  // a real location, so we calculate it to be coincident to the base
475  // facet, and then orient it so that the vertex of V which is not
476  // part of the new simplex is on the other side of the constraint
477  PointRef p_excluded = V->vertices[ridge.iExcluded];
478  simplex->calculateConstraint( m_ndim, m_deref );
479  simplex->orientConstraint( m_deref(p_excluded),
481  }
482 
483 
484  // ok now that all the new simplices have been added, we need to go
485  // and assign neighbors to these new simplicies
486  for( size_t i=0; i < nHorizon; i++ )
487  {
488  HorizonRidge_t& ridge = m_ridges[i];
489  Simplex* simplex = ridge.generatedSimplex;
490  Simplex* V = ridge.simplex;
491 
492  // set of vertices of the new simplex, note that we exclude i=0
493  // which is the anti-origin, and iExclude, which is x
494  PointSet vertices_f;
495  for(int i=1; i < m_ndim+1; i++)
496  vertices_f.insert( simplex->vertices[i] );
497 
498  // we need to find all of the neighbors except for the iExcluded
499  // one and for the one across the base facet
500  for(int i=1; i < m_ndim+1; i++)
501  {
502  if( i == ridge.iExcluded )
503  continue;
504 
505  PointRef q = simplex->vertices[i];
506  Simplex* from = 0;
507  Simplex* next = V;
508  Simplex* S = 0;
509 
510  // first, we remove q from vertices(f), note that there are
511  // now d-1 points in this set, defining a d-2 face (simplex?)
512  vertices_f.erase(q);
513 
514  // It is guarenteed that V is in the set script S. So we start
515  // at V and find it's neighbor who is also in script S
516  // (if it exists). Then we continue a walk in this manner,
517  // because each element of script S has at most two
518  // neighbors in script S.
519  while(next != S)
520  {
521  from = S;
522  S = next;
523  for(int j=0; j < m_ndim+1; j++)
524  {
525  Simplex* candidate = S->neighbors[j];
526  if( candidate != from
527  && candidate->vertices[0] == x)
528  {
529  // in order to be in Script S, other than x, it can
530  // have at most 2 vertex not in vertices_f - q,
531  int nFail = 0;
532  for(int k=1; k < m_ndim+1; k++)
533  {
534  if( vertices_f.find(candidate->vertices[k])
535  == vertices_f.end() )
536  {
537  nFail++;
538  if(nFail > 2)
539  break;
540  }
541  }
542 
543  if(nFail < 3)
544  {
545  // if candidate is not the neighbor we entered from,
546  // and has x as a peak, and contains only one vertex
547  // not in vertices(f) \ q, then it must be a member
548  // of Script S.
549  next = candidate;
550  break;
551  }
552  }
553  }
554 
555  }
556 
557  // now that we're here, the base facet of S must be composed
558  // of vertices_f \ q U {y1, y2}. Furthemore the neighbor
559  // opposite y2 must be the neighbor that we entered S by
560  // (or q in the the case of a zero length path). So we need
561  // to identify which of the vertices is y1, which will give us
562  // the neighbor of the new simplex opposite q
563  int iy1 = 0;
564 
565  // first check the case that V = V'
566  if( S == V )
567  {
568  for(int j=1; j < m_ndim+1; j++)
569  {
570  Simplex* neighbor = S->neighbors[j];
571  PointRef vertex = S->vertices[j];
572 
573  if(vertex == q)
574  {
575  iy1 = j;
576  break;
577  }
578  }
579  }
580 
581  else
582  {
583  // note that we don't check j=0 because we're interested only
584  // in the vertices on the base
585  for(int j=1; j < m_ndim+1; j++)
586  {
587  Simplex* neighbor = S->neighbors[j];
588  PointRef vertex = S->vertices[j];
589 
590  // this vertex is y2 then just keep searching
591  if( neighbor == from )
592  continue;
593 
594  // otherwise, check to see if this vertex is not in
595  // vertices_f
596  if( vertices_f.find(vertex) == vertices_f.end() )
597  {
598  iy1 = j;
599  break;
600  }
601  }
602  }
603 
604  // ok, now that we've found iy2, it shoudl be that the i'th
605  // neighbor of the new simplex, i.e. the neighbor opposite
606  // q is the neighbor opposite the y2 of S.
607  simplex->neighbors[i] = S->neighbors[iy1];
608 
609  // now we put q back into vertices(f)
610  vertices_f.insert(q);
611  }
612  }
613 }
614 
615 
616 
617 
618 
619 } // namespace dynamic
620 } // namespace clarkson93
621 } // namespace mpblocks
622 
623 
624 
625 
626 
627 #endif // TRIANGULATION_HPP_
has been queued during the x-visible walk
Definition: Simplex.h:41
priority queue node
Definition: Indexed.h:38
void insert(const PointRef x, Simplex *S=0)
insert a new point into the triangulation and update the convex hull (if necessary) ...
VertexSurrogate< ArrayLike > vertex(const ArrayLike &v)
Definition: CertSet.h:151
void find_x_visible(PointRef x, Simplex *S=0)
find the set of facets and put them in x_visible
is queued for expansion in x-visible search
Definition: Simplex.h:43
void init(Iterator begin, Iterator end)
builds the initial triangulation from the first NDim + 1 points inserted
void setup(Setup &setup)
set's up the triangulation by helping it construct it's allocators and preallocate it's sets ...
A horizon ridge is a d-2 dimensional facet (i.e. a facet of a facet),.
Definition: HorizonRidge.h:39
void clear()
destroys all simplex objects that have been generated and clears all lists/ sets