versor  3.0
C++11 library for Geometric algebra
vsr_graph.h
1 
2 
3 #ifndef VSR_GRAPH_H_INCLUDED
4 #define VSR_GRAPH_H_INCLUDED
5 
6 #include "vsr_set.h"
7 //#include "vsr_smart.h"
8 
9 namespace vsr{
10 
17  template<class T>
18  struct HEGraph {
19 
20  struct HalfEdge;
21  struct Face;
22  struct Node;
23 
24 
30  struct Node {
31 
32  Node() : ptr(NULL), edge(NULL), bVisited(false){}
33 
34  T * ptr;
36 
37  bool bVisited;
38 
40  T& data() { return *ptr; }
41  T data() const { return *ptr; }
42 
43  Node& data( T& v ) { ptr = &v; return *this; }
44 
46  vector<HalfEdge*> valence() const;
47 
49  vector<HalfEdge*> edgeLoop() const;
50 
52  bool closed() const;
53 
54  // bool bClosed; //maybe save state for cheaper comp
55 
57  HalfEdge& null();
58 
60  vector<HalfEdge*> nulls();
61 
63  vector<Face*> faces();
64 
66  vector<Node*> neighbors();
67 
68  void visited(bool t) { bVisited=t; }
69  bool visited(){ return bVisited; }
70  void reset() { bVisited=false; }
71 
72  };
73 
74 
75 
76 
80  struct HalfEdge{
81 
82  //int id;
83 
84  HalfEdge() : node(NULL), face(NULL), opp(NULL), next(NULL), bVisited(false)
85  {}
86 
87  bool bVisited;
88 
89  Node * node; // Incident vertex
90  Face * face; // Face membership
91 
92  HalfEdge * opp; // Opposite half-edge
93  HalfEdge * next; // Next half-edge counterclockwise
94 
95  HalfEdge& prev() { return *(next -> next); }
96 
97  T& a() { return node -> data(); }
98  T& b() { return prev().node -> data(); }
99 
100  bool isBorder() { return opp == NULL; }
101 
102  void set( HalfEdge& e){
103  node = &(*e.node);
104  face = &(*e.face);
105  opp = &(*e.opp);
106  next = &(*e.next);
107  }
108 
112  HalfEdge& nextNull(bool clockwise){
113 
114  if (clockwise){
115  HalfEdge * e = next -> opp;
116  HalfEdge * t = next;
117  while (e !=NULL){
118  t = e -> next;
119  e = e -> next -> opp;
120  }
121  return *t;
122  } else {
123  HalfEdge * e = next -> next -> opp;
124  HalfEdge * t = next -> next;
125  while (e !=NULL){
126  t = e -> next -> next;
127  e = e -> next -> next -> opp;
128  }
129  return *t;
130 
131  }
132  }
133 
135  bool ccwFrom( HalfEdge& eb ){
136  if ( node == eb.prev().node ) return true;
137  return false;
138  }
139  bool cwFrom( HalfEdge& eb){
140  if ( prev().node == eb.node ) return true;
141  return false;
142  }
143 
145  bool isOpp( HalfEdge& eb ){
146  if ( ( node == eb.prev().node ) && ( prev().node == eb.node ) ) return true;
147  return false;
148  }
149 
151  void seal( HalfEdge& eb) {
152  opp = &eb; eb.opp = this;
153  }
154 
155  /* vector< HalfEdge* > edgeLoop(){ */
156 
157  /* } */
158 
160  bool triangle(){
161  auto& eb = nextNull(false);
162  if ( &nextNull(true) == &(eb.nextNull(false)) ) return true;
163  else return false;
164  }
165 
167  /* vector<HalfEdge*> loop(){ */
168  /* vector<HalfEdge*> redge; */
169  /* HalfEdge * te; */
170  /* do{ */
171  /* if ( (next->opp)!=NULL) { */
172  /* te = next->opp->next; */
173  /* } else{ */
174  /* te = next; */
175  /* } */
176  /* redge.push_back(te); */
177  /* return redge; */
178  /* } */
179 
180 
181 
182  };
183 
184 
185  struct Face {
186 
187  Face() : edge(NULL) {}
188 
189  HalfEdge * edge; //Any edge
190 
191  HalfEdge& ea() { return *edge; }
192  HalfEdge& eb() { return *(edge->next); }
193  HalfEdge& ec() { return *(edge->next->next); }
194 
195  /* HalfEdge ea() const { return *edge; } */
196  /* HalfEdge eb() const { return *(edge->next); } */
197  /* HalfEdge ec() const { return *(edge->next->next); } */
198 
199  Node& na() { return * ( ea().node ); }
200  Node& nb() { return * ( eb().node ); }
201  Node& nc() { return * ( ec().node ); }
202 
203  /* Node na() const { return * ( ec().node ); } */
204  /* Node nb() const { return * ( ea().node ); } */
205  /* Node nc() const { return * ( eb().node ); } */
206 
207 
208  T& a() { return na().data() ; }
209  T& b() { return nb().data() ; }
210  T& c() { return nc().data() ; }
211 
212  /* T a() const { return na().data() ; } */
213  /* T b() const { return nb().data() ; } */
214  /* T c() const { return nc().data() ; } */
215 
216  vector<Face*> edgeNeighbors(){
217  vector<Face*> vp;
218 
219  if ( ea().opp != NULL ) vp.push_back( ea().opp -> face );
220  if ( eb().opp != NULL ) vp.push_back( eb().opp -> face );
221  if ( ec().opp != NULL ) vp.push_back( ec().opp -> face );
222 
223  return vp;
224  }
225 
226 
227 
228  };
229 
230 
231 
232 
233  //METHODS
234  //once three nodes exist, seed them into a facet (starts with b)
235  void seedNodes(){
236 
237  Node *na, *nb, *nc;
238  HalfEdge *ea, *eb, *ec;
239  Face *f;
240 
241  na = &(*(mNode[0])); nb = &(*( mNode[1] )); nc = &(*(mNode[2]));
242 
243 
244  ea = new HalfEdge;
245  eb = new HalfEdge;
246  ec = new HalfEdge;
247 
248  f = new Face();
249 
250  //Assign a edge incident to b, b edge incident to c, etc
251  ea -> node = na;//nb;
252  eb -> node = nb;//nc;
253  ec -> node = nc;//na;
254 
255  f -> edge = ea; //Pick any old edge
256 
257  na -> edge = eb; //emanating
258  nb -> edge = ec;
259  nc -> edge = ea;
260 
261  ea -> next = eb; ea -> face = f; // assign next edge and face
262  eb -> next = ec; eb -> face = f;
263  ec -> next = ea; ec -> face = f;
264 
265  //Store
266  mHalfEdge.push_back(ea);
267  mHalfEdge.push_back(eb);
268  mHalfEdge.push_back(ec);
269 
270  mFace.push_back(f);
271 
272  }
273 
274 
275  void facet( HalfEdge * ea, HalfEdge * eb, HalfEdge * ec, Face * f){
276 
277  ea -> next = eb; eb -> next = ec; ec -> next = ea;
278  ea -> face = f; eb -> face = f; ec -> face = f;
279 
280  f -> edge = ea;
281 
282  }
283 
284  //preliminary
285  Node& addNode( T& v ){
286  Node * n = new Node;
287  n -> ptr = &v;
288  mNode.push_back( n );
289  return *n;
290  }
291 
292  //add faces and edges to nodes that already exist
293  HEGraph& fillFace( int a, int b, int c ){
294 
295  Node *na, *nb, *nc;
296  HalfEdge *ea, *eb, *ec;
297  Face *f;
298 
299  na = mNode[a];
300  nb = mNode[b];
301  nc = mNode[c];
302 
303  ea = new HalfEdge;
304  eb = new HalfEdge;
305  ec = new HalfEdge;
306 
307  f = new Face();
308 
309  na -> edge = eb; //emanating
310  nb -> edge = ec;
311  nc -> edge = ea;
312 
313  //Assign a edge incident to b, b edge incident to c, etc
314  ea -> node = na;//nb;
315  eb -> node = nb;//nc;
316  ec -> node = nc;//na;
317 
318  mHalfEdge.push_back(ea);
319  mHalfEdge.push_back(eb);
320  mHalfEdge.push_back(ec);
321 
322  mFace.push_back(f);
323 
324 
325  facet(ea,eb,ec,f);
326 
327  return *this;
328 
329  }
330 
331 
332  HEGraph& add( T& v ) {
333  int num = mNode.size();
334  if (num < 3 ) addNode( v );
335  if (num == 2 ) seedNodes(); //if num was 2 coming in, it is now 3 so seed
336  if (num >= 3 ) addAt ( v, lastEdge() );
337  return *this;
338  }
339 
340 
341 
342  //add a new Node (and Face) To Some Edge (creates three new half edges, a new node and a new face)
343  HEGraph& addAt( T& v, HalfEdge& e ){
344 
345  Node * n = new Node;
346 
347  HalfEdge * ea = new HalfEdge;
348  HalfEdge * eb = new HalfEdge;
349  HalfEdge * ec = new HalfEdge;
350 
351  Face * f = new Face;
352 
353  //pick an edge
354  f -> edge = ea;
355 
356  //basic facet
357  ea -> next = eb; eb -> next = ec; ec -> next = ea;
358  ea -> face = f; eb -> face = f; ec -> face = f;
359 
360  //incidence: ea is outgoing edge from new node, ec is incident edge to it, eb shares with argument
361  n -> ptr = &v;
362  n -> edge = ea;
363  ec -> node = n;
364 
365  e.opp = eb; eb -> opp = &e;
366 
367  ea -> node = e.node;
368  eb -> node = e.next -> next -> node;
369 
370  //Store
371  mNode.push_back(n);
372 
373  mHalfEdge.push_back(ea);
374  mHalfEdge.push_back(eb);
375  mHalfEdge.push_back(ec);
376 
377  mFace.push_back(f);
378 
379  return *this;
380  }
381 
382  HEGraph& addAt( T& v, int x ){
383  return addAt(v, edge(x));
384  }
385 
386  //Given Four Points, make two triangles
387  void seed( T& a, T& b, T& c, T& d){
388  seed(a,b,c); add(d, lastEdge() );
389  }
390 
391  //Insert new point on Edge make new face "downstream"
392  void insert( T& pa, HalfEdge& e){
393 
394  //Three new halfedges, one new Node and one new Face
395  HalfEdge * ea, *eb, *ec;
396  Node * n = new Node;
397  Face * f = new Face;
398 
399  ea = new HalfEdge; eb = new HalfEdge; ec = new HalfEdge;
400 
401  //Assign, new face
402  ea -> set( e ); //equal . . .
403  ea -> face = f; f -> edge = ea; // . . . except for face
404 
405  ec->opp = eb; eb->opp = ec;
406  ec->next = ea;
407  ec->node = n;
408  ec->face = f;
409 
410  eb->node = &(*(e.next -> node));
411  eb->next = &(*(e.next -> next));
412  eb->face = &(*(e.face));
413 
414  n -> ptr = &pa; n -> edge = ea;
415 
416  e.next -> face = f;
417  e.next -> next = ec;
418 
419  e.node = n; e.next = eb;
420  e.face -> edge = &e;
421 
422  //Store
423  mNode.push_back(n);
424 
425  mHalfEdge.push_back( eb );
426  mHalfEdge.push_back( ec );
427  mHalfEdge.push_back( ea );
428 
429  mFace.push_back( f );
430 
431  }
432 
434  void close( HalfEdge& ha, HalfEdge& hb){
435 
436  //add an edge and a face
437  Face * f = new Face;
438 
439  HalfEdge *ea, *eb, *ec;
440  ea = new HalfEdge; eb = new HalfEdge; ec = new HalfEdge;
441 
442  //make facet
443  facet( ea,eb,ec,f);
444 
445  ea -> node = hb.prev().node;
446  ec -> node = hb.node;
447  eb -> node = ha.prev().node;
448 
449  ha.opp = eb; eb -> opp = &ha;
450  hb.opp = ea; ea -> opp = &hb;
451 
452  mHalfEdge.push_back( ea );
453  mHalfEdge.push_back( eb );
454  mHalfEdge.push_back( ec );
455 
456  mFace.push_back( f );
457  }
458 
459  // close edge and node
460  void close( HalfEdge& e, Node& n){
461 
462  //a new face
463  Face * f = new Face;
464 
465  //3 new halfEdges
466  HalfEdge *ea, *eb, *ec;
467  ea = new HalfEdge; eb = new HalfEdge; ec = new HalfEdge;
468 
469  //make facet
470  facet( ea,eb,ec,f);
471 
472  ea -> node = e.node;
473  eb -> node = e.prev().node;
474  ec -> node = &n;
475 
476  e.opp = eb; eb -> opp = &e;
477 
478  mHalfEdge.push_back( ea );
479  mHalfEdge.push_back( eb );
480  mHalfEdge.push_back( ec );
481 
482  mFace.push_back( f );
483 
484 
485  }
486 
487  //Close Simple Triangle Hole
488  void close( HalfEdge& e ){
489  //add edges and a face
490  Face * f = new Face;
491 
492  HalfEdge *ea, *eb, *ec;
493  ea = new HalfEdge; eb = new HalfEdge; ec = new HalfEdge;
494 
495  //make facet
496  facet( ea,eb,ec,f);
497 
498  auto& tb = e.nextNull(false);
499  auto& tc = e.nextNull(true);
500 
501  ea -> node = tb.node;
502  eb -> node = tc.node;
503  ec -> node = e.node;
504 
505  ea -> opp = &e; e.opp = ea;
506  eb -> opp = &tb; tb.opp = eb;
507  ec -> opp = &tc; tc.opp = ec;
508 
509  mHalfEdge.push_back( ea );
510  mHalfEdge.push_back( eb );
511  mHalfEdge.push_back( ec );
512 
513  mFace.push_back( f );
514 
515  }
516 
517  //removes a face
518  void removeFacet( int idx ) {
519 
520  }
521 
522  //removes an edge
523  void removeEdge( int idx ) {
524 
525  }
526 
527  //given an edge loop around a node, find next outer edge loop
528  vector<HalfEdge*> edgeLoop0( vector<HalfEdge*> loop ){//const Node& n){
529 
530  vector<HalfEdge*> result;
531 
532  if (!loop.empty()){
533  //pick one node and get emanating edges
534  auto v = loop[0]->node->valence();
535  //find first one that is does not point to any node on current loop
536  HalfEdge * first = NULL;
537  for (auto& i : v){
538  bool bExists=false;
539  for (auto& j : loop){
540  if (j->node==i->node){
541  bExists=true;
542  break;
543  }
544  }
545  if (!bExists){
546  first=i;
547  break;
548  }
549  }
550 
551  //assuming we found a new emanating edge, add all first
552  //cw edges that don't point back
553  //until we get back to first or hit border
554  HalfEdge * tmp = first;
555  while (tmp!=NULL && (tmp->node != first->node) ){
556 
557  bool bExists=false;
558  tmp = tmp->next;
559  for (auto& j : loop){
560  if (j->node==tmp->node){
561  bExists=true;
562  break;
563  }
564  }
565  if (bExists) tmp = tmp->opp; //repeat
566  else {
567  result.push_back(tmp);
568  }
569  }
570  }
571 
572  return result;
573  }
574 
575 
576  vector<HalfEdge*> emanatingEdges( vector<HalfEdge*> loop ){
577 
578  HalfEdge * first = NULL;
579 
580  vector<HalfEdge*> result;
581 
582  for(auto& i : loop){
583  if (i->opp!=NULL){
584  result.push_back(i->opp->next);
585  }
586  }
587  return result;
588  }
589 
590  vector<HalfEdge*> edgeLoop( vector<HalfEdge*> loop ){
591 
592  int maxNum = 100;
593 
594  vector<HalfEdge*> result;
595  HalfEdge * tmp = NULL;
596 
597  if (!loop.empty()){
598 
599  //does loop close?
600  bool bClosed = loop.back()->node == loop[0]->prev().node;
601 
602  //Get Emanating Edges
603  auto edges = emanatingEdges(loop);
604 
605  //if not closed, connect edge to first emanating edge
606  //(if first emanating edge isn't already on border)
607  if (!bClosed){
608  if (!edges.empty()){
609  tmp=edges[0];
610  if (!tmp->isBorder()){
611  int iter =0;
612  while (!tmp->isBorder() && iter<maxNum){
613  tmp=tmp->opp->next;
614  iter++;
615  }
616  result.push_back(tmp);
617  tmp = tmp->next;
618  result.push_back(tmp);
619 
620  iter =0;
621  while(tmp->node != edges[0]->node && iter<maxNum){
622  tmp = tmp->next->opp->next;
623  result.push_back(tmp);
624  iter++;
625  }
626  } else if (edges.size()>2) {
627  result.push_back(tmp);
628  }
629 
630  }
631  }
632 
633  //Connect emanating edges (avoiding original loop's nodes)
634  for (int i=0; i<edges.size();++i){
635  tmp = edges[i];
636  int nxt = i<edges.size()-1 ? i+1 : 0;
637  int iter =0;
638  while ( tmp!=NULL && tmp->node != edges[nxt]->node && iter < maxNum){
639  iter++;
640  tmp = tmp->next;
641 
642  bool bExists=false;
643  for (auto& j : loop){
644  if ( (j->node==tmp->node) || (j->next->next->node==tmp->node) ){
645  bExists=true;
646  break;
647  }
648  }
649 
650  if (bExists) {
651  if (tmp->opp==NULL){
652  result.push_back(tmp);
653  }
654  tmp = tmp->opp;
655  } else {
656  result.push_back(tmp);
657  }
658  }
659  }
660 
661  }
662 
663  return result;
664  }
665 
666 
667  //all nodes connected to a node
668  /* vector<Node*> nodeLoop( Node& a){ */
669  /* vector<Node*> tmp; */
670  /* for (auto i : edgeLoop(a) ) tmp.push_back( i -> node ); */
671  /* } */
672 
674  vector<HalfEdge*> nullEdges(){
675  vector<HalfEdge*> tmp;
676  for (auto& i : mHalfEdge){
677  if ( i -> isBorder() ) tmp.push_back(i);
678  }
679  return tmp;
680  }
681 
683  bool hasBorder(){
684  for (auto& i : mHalfEdge){
685  if ( i -> isBorder() ) return true;
686  }
687  return false;
688  }
689 
691  HalfEdge& firstNull(){
692  for (auto& i : mHalfEdge){
693  if ( i -> isBorder() ) return *i;
694  }
695  }
696 
698  vector<HalfEdge*> nullEdgeLoop(){
699 
700  vector<HalfEdge*> tmp;
701  int it = -1;
702 
703  for (int it = 0; it < mHalfEdge.size(); ++it){
704 
705  if ( mHalfEdge[it] -> opp != NULL ) continue;
706 
707  else {
708 
709  HalfEdge * he = mHalfEdge[it];
710 
711  do{
712  tmp.push_back( he );
713  he = &(he -> nextNull() );
714  } while ( he != mHalfEdge[it] );
715 
716  return tmp;
717  }
718  }
719  }
720 
721 
722  //methods
723  void reset() {
724  for (auto& i : mHalfEdge){
725  i -> bVisited = false;
726  }
727  for (auto& i : mNode){
728  i -> visited(false);
729  }
730  }
731 
732  void clear() {
733  mHalfEdge.clear();
734  mFace.clear();
735  mNode.clear();
736  }
737 
738  //Most recently added elements of graph
739  HalfEdge& lastEdge() { return *mHalfEdge.back(); }
740  Face& lastFace() { return *mFace.back(); }
741  Node& lastNode() { return *(mHalfEdge.back() -> node); }
742 
743  Face& face( int idx ) { return *mFace[idx]; }
744 // HalfEdge& edge( int idx ) { return *mHalfEdge[ (mHalfEdge.size() - 1) + idx ]; } //testing this for negative indiices
745  HalfEdge& edge( int idx ) { return idx < 0 ? *mHalfEdge[ mHalfEdge.size() + idx ] : *mHalfEdge[idx]; }
746  // HalfEdge edge( int idx ) const { return idx < 0 ? *mHalfEdge[ mHalfEdge.size() + idx ] : *mHalfEdge[idx]; }
747  Node& node( int idx ) { return *mNode[idx]; }
748 
749 
750  vector<HalfEdge*>& edge() { return mHalfEdge; }
751  vector<Face*>& face() { return mFace; }
752  vector<Node*>& node() { return mNode; }
753 
754  vector<HalfEdge*> edge() const { return mHalfEdge; }
755  vector<Face*> face() const { return mFace; }
756  vector<Node*> node() const { return mNode; }
757 
758  //GENERIC ux, uy GRAPHING UTIL
759  template<class S>
760  HEGraph& UV(int w, int h, S& p, bool bCloseU=false,bool bCloseV=false);
761 
762  private:
763 
764  vector<HalfEdge*> mHalfEdge;
765  vector<Face*> mFace;
766  vector<Node*> mNode;
767 
768  //some data container (unnecessary?)
769  //vector<T> * data;
770 
771  };
772 
773 
774  //NODE METHODS
775  template<class T>
777  HEGraph::HalfEdge * e = edge -> opp;
778  while ( e != NULL && e != edge -> next -> next ){
779  e = e -> next -> opp;
780  }
781  return *e;
782  }
783 
784  template<class T>
785  inline bool HEGraph<T>::Node::closed() const{
786  HEGraph<T>::HalfEdge * e = edge -> opp;
787  if (e == NULL) return false;
788  while ( e != edge -> next -> next ){
789  e = e -> next -> opp;
790  if (e == NULL) return false;
791  }
792  return true;
793  }
794 
795  template<class T>
796  inline vector< typename HEGraph<T>::HalfEdge* > HEGraph<T>::Node::nulls(){
797  vector<HEGraph<T>::HalfEdge*> tmp;
798  HEGraph<T>::HalfEdge * e = edge -> opp;
799  while ( e != NULL && e != edge -> next -> next ){
800  e = e -> next -> opp;
801  }
802  if (e == NULL ){
803  tmp.push_back( e );
804  e = edge -> next -> next -> opp;
805  while ( e != NULL ){
806  e = e -> next -> next -> opp;
807  }
808  tmp.push_back(e);
809  }
810  return tmp;
811  }
812 
813 
814  //edge loop around a node collects (emanating) edges
815  template<class T>
816  inline vector<typename HEGraph<T>::HalfEdge*> HEGraph<T>::Node::valence() const {
817  vector<HEGraph<T>::HalfEdge*> tmp;
818  HEGraph<T>::HalfEdge * e = edge;
819 
820  if (closed()){
821 
822  do {
823  tmp.push_back(e);
824  e = e -> next -> next -> opp;
825  } while( e != edge );
826 
827  return tmp;
828 
829  } else {
830  //if it doesn't loop around to the beginning,
831  //iterate to end in clockwise direction, and then add in counter clockwise
832  auto te = edge->opp;
833  while (te != NULL ){
834  e = te->next;
835  te = te->next->opp;
836  }
837  //now e is cw most edge, add in all . . . there will always be one node left..
838  while(e != NULL){
839  tmp.push_back(e);
840  e = e -> next -> next -> opp;
841  }
842  }
843  return tmp;
844  }
845 
846  template<class T>
847  inline vector<typename HEGraph<T>::HalfEdge*> HEGraph<T>::Node::edgeLoop() const {
848  vector<HEGraph<T>::HalfEdge*> tmp;
849  auto v = valence();
850  for(auto& i : v){
851  tmp.push_back(i->next);
852  }
853  return tmp;
854  }
855 
856 
857 
858  //faceloop around a node collects faces
859  template<class T>
860  inline vector<typename HEGraph<T>::Face*> HEGraph<T>::Node::faces(){
861  vector<HEGraph<T>::Face*> tmp;
862  for (auto& i : valence() ){
863  tmp.push_back( i -> face );
864  }
865  }
866  //for each in valence, add in node at other end (plus last node if open)
867  template<class T>
868  inline vector<typename HEGraph<T>::Node*> HEGraph<T>::Node::neighbors(){
869  vector<typename HEGraph<T>::Node*> tmp;
870  auto res = valence();
871  for(auto& i : res){
872  tmp.push_back( i->node );
873  }
874  if( !closed() ) tmp.push_back( res.back()->next->node );
875  return tmp;
876  }
877 
878  /* //for each in valence, add next to get edge loop */
879  /* template<class T> */
880  /* inline vector<typename HEGraph<T>::Node*> HEGraph<T>::Node::edgeLoop(){ */
881  /* vector<typename HEGraph<T>::Node*> tmp; */
882  /* auto res = valence(); */
883  /* for(auto& i : res){ */
884  /* tmp.push_back( i->node ); */
885  /* } */
886  /* if( !closed() ) tmp.push_back( res.back()->next->node ); */
887  /* return tmp; */
888  /* } */
889 
890 
891 
892  /*-----------------------------------------------------------------------------
893  * c <--d
894  * | \ ^
895  * | \ |
896  * a--->b
897  *-----------------------------------------------------------------------------*/
899  template<class T> template<class S>
900  inline HEGraph<T>& HEGraph<T>::UV(int w, int h, S& p, bool bCloseU, bool bCloseV){
901  HEGraph<T>& graph = *this;
902  //left column
903  for (int j = 0; j < h; ++j){
904  int idx = j;
905  int idxB = j+h;
906  //add first two points
907  if (j<2) graph.add( p[idx] );//adds a, c
908  else graph.addAt( p[idx], graph.edge(-3) );
909  //add next row over
910  if (j==0) graph.add( p[idxB] );//adds b
911  //else if (j<2) graph.addAt( p[idxB], graph.edge(-3) );
912  else graph.addAt( p[idxB], graph.edge(-1) ); //add to last edge
913  }
914 
915  for (int i = 2; i < w; ++i){
916  int idx = ((i-2) * (h-1) + 1)*6 -1;
917  int pidx = i * h;
918  int pidxB = pidx + 1;
919  graph.addAt( p[pidx], graph.edge( idx ) );
920  graph.addAt( p[pidxB], graph.edge(-3) );
921  for (int j = 2; j < h; ++j){
922  int pidxC = i * h + j;
923  graph.close( graph.edge(-3), graph.edge( idx + (j-1) * 6 ) );
924  graph.add( p[pidxC] );
925  }
926  }
927 
928  if (bCloseU){
929  for (int j=0;j<h-1;++j){
930  int idxR = ((w-2)*(h-1)+j+1)*6;
931  int idxL = j*6;
932  graph.close( graph.edge(idxR), *graph.edge(idxL).node);
933  }
934  }
935  if (bCloseV){
936  if(!bCloseU){
937  graph.close( graph.edge(6*(h-1)-3), graph.node(0) );
938  graph.close( graph.lastEdge(), *graph.node(0).edge );
939  for (int i=1;i<w-1;++i){
940  int idxB = (i*(h-1))*6+2;
941  int idxT = ((i+1)*(h-1)*6)-3;
942  graph.close( graph.edge(idxT), *graph.edge(idxB).prev().node);
943  graph.close( graph.lastEdge(), graph.edge(idxB) );
944  }
945  }else{}
946  }
947 
948 
949 
950  return graph;
951  }
952 
953 } //vsr::
954 
955 
956  /* struct Corner { */
957  /* Corner next, prev; // next / prev corners in face */
958  /* HalfEdge hedge; */
959  /* Edge edge; // incoming edge */
960  /* Node node; // incident vertex */
961  /* }; */
962 
963  //given three points, make new facet connecting them (deprecate)
964  /* void seed( T& pa, T& pb, T& pc){ */
965 
966  /* //Create */
967  /* Node *na, *nb, *nc; */
968  /* HalfEdge *ea, *eb, *ec; */
969  /* Face *f; */
970 
971  /* na = new Node; nb = new Node; nc = new Node; */
972 
973  /* ea = new HalfEdge; */
974  /* eb = new HalfEdge; */
975  /* ec = new HalfEdge; */
976 
977  /* f = new Face(); */
978 
979  /* //Assign a edge incident to b, b edge incident to c, etc */
980  /* ea -> node = nb; */
981  /* eb -> node = nc; */
982  /* ec -> node = na; */
983 
984  /* na -> ptr = &pa; */
985  /* nb -> ptr = &pb; */
986  /* nc -> ptr = &pc; */
987 
988  /* f -> edge = ea; //Pick any old edge */
989 
990  /* na -> edge = ea; nb -> edge = eb; nc -> edge = ec; */
991 
992  /* ea -> next = eb; ea -> face = f; // assign next edge and face */
993  /* eb -> next = ec; eb -> face = f; */
994  /* ec -> next = ea; ec -> face = f; */
995 
996  /* //Store */
997  /* mNode.push_back(na); */
998  /* mNode.push_back(nb); */
999  /* mNode.push_back(nc); */
1000 
1001  /* mHalfEdge.push_back(ea); */
1002  /* mHalfEdge.push_back(eb); */
1003  /* mHalfEdge.push_back(ec); */
1004 
1005  /* mFace.push_back(f); */
1006 
1007  /* } */
1008  //last edge and point (or node??)
1009  /* void close( T& p ){ */
1010  /* //should make a new face */
1011  /* Face * f = new Face; */
1012 
1013  /* HalfEdge *ea = new HalfEdge; */
1014  /* HalfEdge *eb = new HalfEdge; */
1015  /* HalfEdge *ec = new HalfEdge; */
1016 
1017  /* ea -> face = f; eb -> face = f; ec -> face = f; */
1018  /* f -> edge = ea; */
1019  /* ea -> next = eb; eb -> next = ec; ec -> next = ea; */
1020 
1021  /* HalfEdge& edge = lastEdge(); */
1022  /* edge.opp = eb; */
1023 
1024  /* mFace.push_back(f); */
1025  /* mHalfEdge.push_back(ea); */
1026  /* mHalfEdge.push_back(eb); */
1027  /* mHalfEdge.push_back(ec); */
1028 
1029  /* } */
1030 
1031  /* //add a route to the halfedge graph */
1032  /* void connect(Node& a, Node& b){ */
1033 
1034  /* //should make a new face */
1035  /* Face * f = new Face; */
1036 
1037  /* HalfEdge *ea = new HalfEdge; */
1038  /* HalfEdge *eb = new HalfEdge; */
1039  /* HalfEdge *ec = new HalfEdge; */
1040 
1041  /* //find the common node */
1042  /* Node * tmp = NULL; */
1043  /* for (auto i : nodeLoop(a) ){ */
1044  /* for (auto j : nodeLoop(b) ){ */
1045  /* if ( i == j ) tmp = i; */
1046  /* break; */
1047  /* } */
1048  /* } */
1049 
1050 
1051  /* mFace.push_back(f); */
1052  /* mHalfEdge.push_back(ea); */
1053  /* mHalfEdge.push_back(eb); */
1054  /* mHalfEdge.push_back(ec); */
1055 
1056 
1057 
1058 
1059 #endif
HalfEdge & null()
Find any null edge of a node.
Definition: vsr_graph.h:776
Definition: vsr_graph.h:185
HalfEdge * edge
An emanating half-edge.
Definition: vsr_graph.h:35
vector< HalfEdge * > edgeLoop() const
Find edge loop (next of edges)
Definition: vsr_graph.h:847
bool ccwFrom(HalfEdge &eb)
Check for shared Node with another HalfEdge.
Definition: vsr_graph.h:135
vector< HalfEdge * > nullEdges()
Get null edges of graph.
Definition: vsr_graph.h:674
bool bVisited
Flag for keeping track of visitation.
Definition: vsr_graph.h:37
Templated half edge structure (pointers to any type) Navigates references to surface topology of data...
Definition: vsr_graph.h:18
HalfEdge & firstNull()
Find first null edge.
Definition: vsr_graph.h:691
bool triangle()
Check for simple Loop (triangle)
Definition: vsr_graph.h:160
A Node stores address of value of type T and pointer to an emanating edge.
Definition: vsr_graph.h:30
vector< HalfEdge * > valence() const
Find all outgoing Edges.
Definition: vsr_graph.h:816
HalfEdge & nextNull(bool clockwise)
Find next null edge (assumes this edge is null) Could be on same face .
Definition: vsr_graph.h:112
vector< Face * > faces()
Find all faces.
Definition: vsr_graph.h:860
bool isOpp(HalfEdge &eb)
Test for partnership.
Definition: vsr_graph.h:145
vector< Node * > neighbors()
Find all Neighboring nodes.
Definition: vsr_graph.h:868
bool closed() const
Test for node closure (no null Edges in loop)
Definition: vsr_graph.h:785
the versor library namespace
Definition: vsr_algebra.h:29
vector< HalfEdge * > nullEdgeLoop()
Get null edge path (boundary) of graph.
Definition: vsr_graph.h:698
T & data()
Get reference to data;.
Definition: vsr_graph.h:40
void seal(HalfEdge &eb)
Seal together two halfedges.
Definition: vsr_graph.h:151
T * ptr
Pointer to type T.
Definition: vsr_graph.h:34
vector< HalfEdge * > nulls()
Find both null edges around a node.
Definition: vsr_graph.h:796
HALF EDGE Data structure
Definition: vsr_graph.h:80
bool hasBorder()
Any Null Edges?
Definition: vsr_graph.h:683
void close(HalfEdge &ha, HalfEdge &hb)
eb /ea counter clockwise
Definition: vsr_graph.h:434