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
21void
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
54void
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
120void
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
197void
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
230void
231GraphTriangulation::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
351void
352GraphTriangulation::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
392GraphTriangulation::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}
std::vector< CSGEdge * > TEdgeList
std::vector< CSGNode * > TNodeList
TSphereCoord getPosition()
TNodeList * getNodes()
int addEdge(int nIndex1, int nIndex2)
TEdgeList * getEdges()
int addNode(CSGNode *pNode)
CSGNode * getNode(int nIndex)
static void delaunayTriangulationQuadratic(CSphericalGraph *pGraph)
static void triangulationQuadraticSpherical(CSphericalGraph *pGraph)
static void triangulationQuartic(CSphericalGraph *pGraph, float fThreshold=FLT_MAX)
static void triangulationQuadratic(CSphericalGraph *pGraph)
static float getDistanceOnArc(TSphereCoord p1, TSphereCoord p2)
static float CalculateCrossProductFromDifference(TSphereCoord p1, TSphereCoord p2, TSphereCoord p3)
static void convert(TSphereCoord in, Eigen::Vector3d &out)
void findClosestNeighbours(CSphericalGraph *pGraph, int &s, int &t)
bool insideCircumcircle(CSphericalGraph *pGraph, int nIndex1, int nIndex2, int nIndex3, int nPointIndex, bool &bInside)
bool getCircumcircle(CSphericalGraph *pGraph, int nIndex1, int nIndex2, int nIndex3, TSphereCoord &center, float &fRadius)
bool isEdgePresent(CSphericalGraph *pGraph, int nIndex1, int nIndex2)
int findEdge(CSphericalGraph *pGraph, int nIndex1, int nIndex2)
double s(double t, double s0, double v0, double a0, double j)
Definition CtrlUtil.h:33
float fTheta
Definition Structs.h:27