GraphTriangulation.cpp
Go to the documentation of this file.
1 // *****************************************************************
2 // Filename: GraphProcessor.cpp
3 // Copyright: Kai Welke, Chair Prof. Dillmann (IAIM),
4 // Institute for Computer Science and Engineering (CSE),
5 // University of Karlsruhe. All rights reserved.
6 // Author: Kai Welke
7 // Date: 12.06.2007
8 // *****************************************************************
9 
10 
11 // *****************************************************************
12 // includes
13 // *****************************************************************
14 // local includes
15 #include "GraphTriangulation.h"
16 
17 #include "Base/Math/MathTools.h"
18 #include "Base/Tools/DebugMemory.h"
19 #include "GraphProcessor.h"
20 
21 void
23 {
24  TC3DNodeList* pC3DNodeList = new TC3DNodeList();
25  int nNodes = (int)pGraph->getNodes()->size();
26 
27  for (int i = 0; i < nNodes; i++)
28  {
29  // project point to polar coordinates
30  Vec3d cartesian_point;
31  MathTools::convert(pGraph->getNode(i)->getPosition(), cartesian_point);
32 
33  CC3DNode* pC3DNode = new CC3DNode(cartesian_point);
34  pC3DNodeList->push_back(pC3DNode);
35  }
36 
37  // generate the delaunay triangulation by computing the
38  // convex hull of the sphere
39  CCHGiftWrap giftWrapping = CCHGiftWrap(pC3DNodeList);
40  CSphericalGraph* pCopy = new CSphericalGraph();
41  giftWrapping.generateConvexHull(pCopy);
42 
43  // add edges from triangulated graph to pGraph
44  TEdgeList* pEdges = pCopy->getEdges();
45 
46  for (int e = 0; e < pEdges->size(); e++)
47  {
48  pGraph->addEdge(pEdges->at(e)->nIndex1, pEdges->at(e)->nIndex2);
49  }
50 
51  delete pCopy;
52 }
53 
54 void
56 {
57  int nNumberViews = (int)pGraph->getNodes()->size();
58 
59  // create graph with nodes and nodes + 360
60  CSphericalGraph* pDoubleGraph = doubleNodes(pGraph);
61 
62  // do triangulation on the double size graph
63  //triangulationQuadratic(pDoubleGraph);
64  triangulationQuartic(pDoubleGraph);
65 
66  // insert detrmined edges in original graph
67  int nIndex1, nIndex2;
68  CSGEdge* pCurrentEdge;
69 
70  for (int e = 0; e < int(pDoubleGraph->getEdges()->size()); e++)
71  {
72  pCurrentEdge = pDoubleGraph->getEdges()->at(e);
73  nIndex1 = pCurrentEdge->nIndex1;
74  nIndex2 = pCurrentEdge->nIndex2;
75 
76  // HACK: delete outer edges
77  if ((pDoubleGraph->getNode(nIndex1)->getPosition().fTheta < 30.0) ||
78  (pDoubleGraph->getNode(nIndex1)->getPosition().fTheta > 690.0))
79  {
80  continue;
81  }
82 
83  if ((pDoubleGraph->getNode(nIndex2)->getPosition().fTheta < 30.0) ||
84  (pDoubleGraph->getNode(nIndex2)->getPosition().fTheta > 690.0))
85  {
86  continue;
87  }
88 
89  /* if( (pDoubleGraph->getNode(nIndex1)->getPosition().fPhi < 30.0) || (pDoubleGraph->getNode(nIndex1)->getPosition().fPhi > 330.0))
90  continue;
91  if( (pDoubleGraph->getNode(nIndex2)->getPosition().fPhi < 30.0) || (pDoubleGraph->getNode(nIndex2)->getPosition().fPhi > 330.0))
92  continue;
93  if( (pDoubleGraph->getNode(nIndex1)->getPosition().fPhi < 180.0) && (pDoubleGraph->getNode(nIndex2)->getPosition().fPhi > 180.0))
94  continue;
95  if( (pDoubleGraph->getNode(nIndex2)->getPosition().fPhi < 180.0) && (pDoubleGraph->getNode(nIndex1)->getPosition().fPhi > 180.0))
96  continue;
97  */
98  // eliminate virtual nodes
99  if (nIndex1 >= nNumberViews)
100  {
101  nIndex1 %= nNumberViews;
102  }
103 
104  if (nIndex2 >= nNumberViews)
105  {
106  nIndex2 %= nNumberViews;
107  }
108 
109  // update graph
110  if (nIndex1 != nIndex2)
111  if (!GraphProcessor::isEdgePresent(pGraph, nIndex1, nIndex2))
112  {
113  pGraph->addEdge(nIndex1, nIndex2);
114  }
115  }
116 
117  delete pDoubleGraph;
118 }
119 
120 void
122 {
123  TNodeList* pNodes = pGraph->getNodes();
124 
125  int nNumberPoints = int(pNodes->size());
126  bool bPointFree;
127  int i, j, k, l;
128 
129  for (i = 0; i < nNumberPoints - 2; i++)
130  {
131  printf("Round %d / %d\n", i, nNumberPoints - 2);
132 
133  for (j = i + 1; j < nNumberPoints - 1; j++)
134  {
135  if (j != i)
136  {
137  for (k = j + 1; k < nNumberPoints; k++)
138  {
139  if (k != i && k != j)
140  {
141 
142  // check if this rectangle is point free
143  bPointFree = true;
144 
145  for (l = 0; l < nNumberPoints; l++)
146  {
147  // only if not one of the triangle points
148  if (l != i && l != j && l != k)
149  {
150  bool bInside;
151 
153  pGraph, i, j, k, l, bInside))
154  {
155  bPointFree = false;
156  break;
157  }
158 
159  if (bInside)
160  {
161  bPointFree = false;
162  break;
163  }
164  }
165  }
166 
167  if (bPointFree)
168  {
169  TSphereCoord p_i, p_j, p_k;
170  p_i = pNodes->at(i)->getPosition();
171  p_j = pNodes->at(j)->getPosition();
172  p_k = pNodes->at(k)->getPosition();
173 
174  // add triangle
175  if (MathTools::getDistanceOnArc(p_i, p_j) < fThreshold)
176  {
177  pGraph->addEdge(i, j);
178  }
179 
180  if (MathTools::getDistanceOnArc(p_i, p_k) < fThreshold)
181  {
182  pGraph->addEdge(i, k);
183  }
184 
185  if (MathTools::getDistanceOnArc(p_k, p_j) < fThreshold)
186  {
187  pGraph->addEdge(k, j);
188  }
189  }
190  }
191  }
192  }
193  }
194  }
195 }
196 
197 void
199 {
200  TEdgeList* pEdges = pGraph->getEdges();
201 
202  int nCurrentEdge;
203  int nFaces = 0;
204  int s = 0, t = 0;
205 
206  // find two closest neighbours and add edge to triangulation.
208 
209  // Create seed edge
210  int nEdgeIndex = pGraph->addEdge(s, t, -1, -1);
211 
212  nCurrentEdge = 0;
213 
214  while (nCurrentEdge < int(pEdges->size()))
215  {
216  if (pEdges->at(nCurrentEdge)->nLeftFace == -1)
217  {
218  completeFacet(pGraph, nCurrentEdge, nFaces);
219  }
220 
221  if (pEdges->at(nCurrentEdge)->nRightFace == -1)
222  {
223  completeFacet(pGraph, nCurrentEdge, nFaces);
224  }
225 
226  nCurrentEdge++;
227  }
228 }
229 
230 void
231 GraphTriangulation::completeFacet(CSphericalGraph* pGraph, int nEdgeIndex, int nFaces)
232 {
233  TNodeList* pNodes = pGraph->getNodes();
234  TEdgeList* pEdges = pGraph->getEdges();
235  int s, t, u;
236 
237  // Cache s and t.
238  if (pEdges->at(nEdgeIndex)->nLeftFace == -1)
239  {
240  s = pEdges->at(nEdgeIndex)->nIndex1;
241  t = pEdges->at(nEdgeIndex)->nIndex2;
242  }
243  else if (pEdges->at(nEdgeIndex)->nRightFace == -1)
244  {
245  s = pEdges->at(nEdgeIndex)->nIndex2;
246  t = pEdges->at(nEdgeIndex)->nIndex1;
247  }
248  else
249  {
250  // Edge already completed.
251  return;
252  }
253 
254 
255  // Find a point on left of edge.
256  for (u = 0; u < int(pNodes->size()); u++)
257  {
258  if (u == s || u == t)
259  {
260  continue;
261  }
262 
263  // check side
264  float fAngle = MathTools::CalculateCrossProductFromDifference(pNodes->at(s)->getPosition(),
265  pNodes->at(t)->getPosition(),
266  pNodes->at(u)->getPosition());
267 
268  if (fAngle > 0.0)
269  {
270  break;
271  }
272  }
273 
274  // Find best point on left of edge.
275  int nBestPoint = u;
276  float fCp;
277 
278  if (nBestPoint < int(pNodes->size()))
279  {
280  TSphereCoord center;
281  float fRadius;
282  GraphProcessor::getCircumcircle(pGraph, s, t, nBestPoint, center, fRadius);
283 
284  for (u = nBestPoint + 1; u < int(pNodes->size()); u++)
285  {
286  if (u == s || u == t)
287  {
288  continue;
289  }
290 
291  fCp = MathTools::CalculateCrossProductFromDifference(pNodes->at(s)->getPosition(),
292  pNodes->at(t)->getPosition(),
293  pNodes->at(u)->getPosition());
294 
295  if (fCp > 0.0)
296  {
297  bool bInside;
298 
299  if (GraphProcessor::insideCircumcircle(pGraph, s, t, nBestPoint, u, bInside))
300  {
301  if (bInside)
302  {
303  nBestPoint = u;
304  }
305  }
306  }
307  }
308  }
309 
310  // Add new triangle or update edge info if s-t is on hull.
311  if (nBestPoint < int(pNodes->size()))
312  {
313  // Update face information of edge being completed.
314  updateLeftFace(pGraph, nEdgeIndex, s, t, nFaces);
315  nFaces++;
316 
317  // Add new edge or update face info of old edge.
318  nEdgeIndex = GraphProcessor::findEdge(pGraph, nBestPoint, s);
319 
320  if (nEdgeIndex == -1)
321  {
322  // New edge.
323  nEdgeIndex = pGraph->addEdge(nBestPoint, s, nFaces, -1);
324  }
325  else
326  {
327  // Old edge.
328  updateLeftFace(pGraph, nEdgeIndex, nBestPoint, s, nFaces);
329  }
330 
331  // Add new edge or update face info of old edge.
332  nEdgeIndex = GraphProcessor::findEdge(pGraph, t, nBestPoint);
333 
334  if (nEdgeIndex == -1)
335  {
336  // New edge.
337  nEdgeIndex = pGraph->addEdge(t, nBestPoint, nFaces, -1);
338  }
339  else
340  {
341  // Old edge.
342  updateLeftFace(pGraph, nEdgeIndex, t, nBestPoint, nFaces);
343  }
344  }
345  else
346  {
347  updateLeftFace(pGraph, nEdgeIndex, s, t, -2);
348  }
349 }
350 
351 void
352 GraphTriangulation::updateLeftFace(CSphericalGraph* pGraph,
353  int nEdgeIndex,
354  int nIndex1,
355  int nIndex2,
356  int nFace)
357 {
358  // vector<TView*>* pViews = &pGraph->getAspectPool()->m_Views;
359  vector<CSGEdge*>* pEdges = pGraph->getEdges();
360 
361  bool bValid = false;
362 
363  if ((pEdges->at(nEdgeIndex)->nIndex1 == nIndex1) &&
364  (pEdges->at(nEdgeIndex)->nIndex2 == nIndex2))
365  {
366  bValid = true;
367  }
368 
369  if ((pEdges->at(nEdgeIndex)->nIndex1 == nIndex2) &&
370  (pEdges->at(nEdgeIndex)->nIndex2 == nIndex1))
371  {
372  bValid = true;
373  }
374 
375  if (!bValid)
376  {
377  printf("updateLeftFace: adj. matrix and edge table mismatch\n");
378  }
379 
380  if ((pEdges->at(nEdgeIndex)->nIndex1 == nIndex1) && (pEdges->at(nEdgeIndex)->nLeftFace == -1))
381  {
382  pEdges->at(nEdgeIndex)->nLeftFace = nFace;
383  }
384  else if ((pEdges->at(nEdgeIndex)->nIndex2 == nIndex1) &&
385  (pEdges->at(nEdgeIndex)->nRightFace == -1))
386  {
387  pEdges->at(nEdgeIndex)->nRightFace = nFace;
388  }
389 }
390 
392 GraphTriangulation::doubleNodes(CSphericalGraph* pSourceGraph)
393 {
394  // list to source views
395  TNodeList* pNodes = pSourceGraph->getNodes();
396  int nNumberSourceNodes = (int)pNodes->size();
397 
398  // add views to aspectpool
399  vector<TSphereCoord> coordinates;
400 
401 
402  for (int i = 0; i < nNumberSourceNodes; i++)
403  {
404  coordinates.push_back(pNodes->at(i)->getPosition());
405  }
406 
407  TSphereCoord shiftedCoord;
408 
409  for (int i = 0; i < nNumberSourceNodes; i++)
410  {
411  shiftedCoord = pNodes->at(i)->getPosition();
412  shiftedCoord.fTheta += 360.0f;
413  coordinates.push_back(shiftedCoord);
414  }
415 
416  /* TSphereCoord shifted2Coord, shifted3Coord;
417  for(int i = 0 ; i < nNumberSourceNodes ; i++)
418  {
419  shifted2Coord = pNodes->at(i)->getPosition();
420  shifted2Coord.fPhi += 180.0f;
421  coordinates.push_back(shifted2Coord);
422  }
423 
424  for(int i = 0 ; i < nNumberSourceNodes ; i++)
425  {
426  shifted3Coord = pNodes->at(i)->getPosition();
427  shifted3Coord.fPhi += 180.0f;
428  shifted3Coord.fTheta += 360.0f;
429  coordinates.push_back(shifted3Coord);
430  }
431  */
432  CSphericalGraph* pTmpGraph = new CSphericalGraph();
433 
434  for (int i = 0; i < 2 * nNumberSourceNodes; i++)
435  {
436  CSGNode* pNode = new CSGNode(coordinates.at(i));
437  pTmpGraph->addNode(pNode);
438  }
439 
440  return pTmpGraph;
441 }
GraphProcessor::findEdge
int findEdge(CSphericalGraph *pGraph, int nIndex1, int nIndex2)
Definition: GraphProcessor.cpp:168
TNodeList
std::vector< CSGNode * > TNodeList
Definition: SphericalGraph.h:100
GraphTriangulation.h
GraphProcessor::insideCircumcircle
bool insideCircumcircle(CSphericalGraph *pGraph, int nIndex1, int nIndex2, int nIndex3, int nPointIndex, bool &bInside)
Definition: GraphProcessor.cpp:190
GfxTL::Vec3d
VectorXD< 3, double > Vec3d
Definition: VectorXD.h:737
TSphereCoord::fTheta
float fTheta
Definition: Structs.h:27
CSphericalGraph::getEdges
TEdgeList * getEdges()
Definition: SphericalGraph.cpp:164
GraphProcessor.h
CSphericalGraph::addNode
int addNode(CSGNode *pNode)
Definition: SphericalGraph.cpp:99
GraphProcessor::isEdgePresent
bool isEdgePresent(CSphericalGraph *pGraph, int nIndex1, int nIndex2)
Definition: GraphProcessor.cpp:314
CSGNode::getPosition
TSphereCoord getPosition()
Definition: SphericalGraph.h:60
CSphericalGraph::addEdge
int addEdge(int nIndex1, int nIndex2)
Definition: SphericalGraph.cpp:109
CSGEdge::nIndex2
int nIndex2
Definition: SphericalGraph.h:36
GraphProcessor::findClosestNeighbours
void findClosestNeighbours(CSphericalGraph *pGraph, int &s, int &t)
Definition: GraphProcessor.cpp:135
CSGEdge
Definition: SphericalGraph.h:31
GraphTriangulation::triangulationQuartic
static void triangulationQuartic(CSphericalGraph *pGraph, float fThreshold=FLT_MAX)
Definition: GraphTriangulation.cpp:121
CSGNode
Definition: SphericalGraph.h:43
GraphProcessor::getCircumcircle
bool getCircumcircle(CSphericalGraph *pGraph, int nIndex1, int nIndex2, int nIndex3, TSphereCoord &center, float &fRadius)
Definition: GraphProcessor.cpp:219
MathTools::CalculateCrossProductFromDifference
static float CalculateCrossProductFromDifference(TSphereCoord p1, TSphereCoord p2, TSphereCoord p3)
Definition: MathTools.cpp:281
GraphTriangulation::triangulationQuadratic
static void triangulationQuadratic(CSphericalGraph *pGraph)
Definition: GraphTriangulation.cpp:198
GraphTriangulation::triangulationQuadraticSpherical
static void triangulationQuadraticSpherical(CSphericalGraph *pGraph)
Definition: GraphTriangulation.cpp:55
CSphericalGraph::getNodes
TNodeList * getNodes()
Definition: SphericalGraph.cpp:170
CSGEdge::nIndex1
int nIndex1
Definition: SphericalGraph.h:35
TEdgeList
std::vector< CSGEdge * > TEdgeList
Definition: SphericalGraph.h:99
GraphTriangulation::delaunayTriangulationQuadratic
static void delaunayTriangulationQuadratic(CSphericalGraph *pGraph)
Definition: GraphTriangulation.cpp:22
MathTools::getDistanceOnArc
static float getDistanceOnArc(TSphereCoord p1, TSphereCoord p2)
Definition: MathTools.cpp:302
CSphericalGraph
Definition: SphericalGraph.h:105
TSphereCoord
Definition: Structs.h:23
MathTools::convert
static void convert(TSphereCoord in, Eigen::Vector3d &out)
Definition: MathTools.cpp:440
armarx::ctrlutil::s
double s(double t, double s0, double v0, double a0, double j)
Definition: CtrlUtil.h:33
CSphericalGraph::getNode
CSGNode * getNode(int nIndex)
Definition: SphericalGraph.cpp:182