GraphGenerator.cpp
Go to the documentation of this file.
1// *****************************************************************
2// Filename: GraphGenerator.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: 08.07.2008
8// *****************************************************************
9
10#include "GraphGenerator.h"
11
12vector<Vec3d> CGraphGenerator::m_Vertices;
13vector<Face> CGraphGenerator::m_Faces;
14
15void
17 EPolyhedronType nBaseType,
18 int nLevels,
19 float fRadius)
20{
21 initBasePolyhedron(nBaseType);
22 projectToSphere(fRadius);
23
24 for (int L = 0; L < nLevels; L++)
25 {
26 subDivide();
27 projectToSphere(fRadius);
28 }
29
30 buildNodesAndEdges(pPlainGraph);
31}
32
33void
34CGraphGenerator::initBasePolyhedron(EPolyhedronType nBaseType)
35{
36 m_Vertices.clear();
37 m_Faces.clear();
38
39 switch (nBaseType)
40 {
41 case eTetrahedron:
42 generateTetrahedron();
43 break;
44
45 case eOctahedron:
46 generateOctahedron();
47 break;
48
49 case eIcosahedron:
50 generateIcosahedron();
51 break;
52
53 default:
54 printf("Wrong base type\n");
55 break;
56 }
57}
58
59void
60CGraphGenerator::generateTetrahedron()
61{
62 // vertices of a tetrahedron
63 float fSqrt3 = sqrt(3.0);
64 Vec3d v[4];
65
66 Math3d::SetVec(v[0], fSqrt3, fSqrt3, fSqrt3);
67 Math3d::SetVec(v[1], -fSqrt3, -fSqrt3, fSqrt3);
68 Math3d::SetVec(v[2], -fSqrt3, fSqrt3, -fSqrt3);
69 Math3d::SetVec(v[3], fSqrt3, -fSqrt3, -fSqrt3);
70
71 for (int i = 0; i < 4; i++)
72 {
73 m_Vertices.push_back(v[i]);
74 }
75
76 // structure describing a tetrahedron
77 Face f[4];
78 f[0].set(1, 2, 3);
79 f[1].set(1, 4, 2);
80 f[2].set(3, 2, 4);
81 f[3].set(4, 1, 3);
82
83 for (int i = 0; i < 4; i++)
84 {
85 f[i].m_n1--;
86 f[i].m_n2--;
87 f[i].m_n3--;
88 m_Faces.push_back(f[i]);
89 }
90}
91
92void
93CGraphGenerator::generateOctahedron()
94{
95 // Six equidistant points lying on the unit sphere
96 Vec3d v[6];
97 Math3d::SetVec(v[0], 1, 0, 0);
98 Math3d::SetVec(v[1], -1, 0, 0);
99 Math3d::SetVec(v[2], 0, 1, 0);
100 Math3d::SetVec(v[3], 0, -1, 0);
101 Math3d::SetVec(v[4], 0, 0, 1);
102 Math3d::SetVec(v[5], 0, 0, -1);
103
104 for (int i = 0; i < 6; i++)
105 {
106 m_Vertices.push_back(v[i]);
107 }
108
109 // Join vertices to create a unit octahedron
110 Face f[8];
111 f[0].set(1, 5, 3);
112 f[1].set(3, 5, 2);
113 f[2].set(2, 5, 4);
114 f[3].set(4, 5, 1);
115 f[4].set(1, 3, 6);
116 f[5].set(3, 2, 6);
117 f[6].set(2, 4, 6);
118 f[7].set(4, 1, 6);
119
120 for (int i = 0; i < 8; i++)
121 {
122 f[i].m_n1--;
123 f[i].m_n2--;
124 f[i].m_n3--;
125 m_Faces.push_back(f[i]);
126 }
127}
128
129void
130CGraphGenerator::generateIcosahedron()
131{
132 // Twelve vertices of icosahedron on unit sphere
133 float tau = 0.8506508084;
134 float one = 0.5257311121;
135
136 Vec3d v[12];
137
138 Math3d::SetVec(v[0], tau, one, 0);
139 Math3d::SetVec(v[1], -tau, one, 0);
140 Math3d::SetVec(v[2], -tau, -one, 0);
141 Math3d::SetVec(v[3], tau, -one, 0);
142 Math3d::SetVec(v[4], one, 0, tau);
143 Math3d::SetVec(v[5], one, 0, -tau);
144 Math3d::SetVec(v[6], -one, 0, -tau);
145 Math3d::SetVec(v[7], -one, 0, tau);
146 Math3d::SetVec(v[8], 0, tau, one);
147 Math3d::SetVec(v[9], 0, -tau, one);
148 Math3d::SetVec(v[10], 0, -tau, -one);
149 Math3d::SetVec(v[11], 0, tau, -one);
150
151 for (int i = 0; i < 12; i++)
152 {
153 m_Vertices.push_back(v[i]);
154 }
155
156
157 // Structure for unit icosahedron
158 Face f[20];
159 f[0].set(5, 8, 9);
160 f[1].set(5, 10, 8);
161 f[2].set(6, 12, 7);
162 f[3].set(6, 7, 11);
163 f[4].set(1, 4, 5);
164 f[5].set(1, 6, 4);
165 f[6].set(3, 2, 8);
166 f[7].set(3, 7, 2);
167 f[8].set(9, 12, 1);
168 f[9].set(9, 2, 12);
169 f[10].set(10, 4, 11);
170 f[11].set(10, 11, 3);
171 f[12].set(9, 1, 5);
172 f[13].set(12, 6, 1);
173 f[14].set(5, 4, 10);
174 f[15].set(6, 11, 4);
175 f[16].set(8, 2, 9);
176 f[17].set(7, 12, 2);
177 f[18].set(8, 10, 3);
178 f[19].set(7, 3, 11);
179
180 for (int i = 0; i < 20; i++)
181 {
182 f[i].m_n1--;
183 f[i].m_n2--;
184 f[i].m_n3--;
185 m_Faces.push_back(f[i]);
186 }
187}
188
189void
190CGraphGenerator::subDivide()
191{
192 // buffer new faces
193 vector<Face> faces;
194
195 // gp through all faces and subdivide
196 for (int f = 0; f < int(m_Faces.size()); f++)
197 {
198 // get the triangle vertex indices
199 int nA = m_Faces.at(f).m_n1;
200 int nB = m_Faces.at(f).m_n2;
201 int nC = m_Faces.at(f).m_n3;
202
203 // get the triangle vertex coordinates
204 Vec3d a = m_Vertices.at(nA);
205 Vec3d b = m_Vertices.at(nB);
206 Vec3d c = m_Vertices.at(nC);
207
208 // Now find the midpoints between vertices
209 Vec3d a_m, b_m, c_m;
210 Math3d::AddVecVec(a, b, a_m);
211 Math3d::MulVecScalar(a_m, 0.5, a_m);
212 Math3d::AddVecVec(b, c, b_m);
213 Math3d::MulVecScalar(b_m, 0.5, b_m);
214 Math3d::AddVecVec(c, a, c_m);
215 Math3d::MulVecScalar(c_m, 0.5, c_m);
216 /* printf("a: %f,%f,%f\n", a.x,a.y,a.z);
217 printf("b: %f,%f,%f\n", b.x,b.y,b.z);
218 printf("c: %f,%f,%f\n", c.x,c.y,c.z);
219
220 printf("a<->b: %f,%f,%f\n", a_m.x,a_m.y,a_m.z);
221 printf("b<->c: %f,%f,%f\n", b_m.x,b_m.y,b_m.z);
222 printf("c<->a: %f,%f,%f\n", c_m.x,c_m.y,c_m.z);*/
223
224 // add vertices
225 int nA_m, nB_m, nC_m;
226
227 int nIndex;
228 nIndex = findVertex(a_m, 0.01);
229
230 if (nIndex == -1)
231 {
232 m_Vertices.push_back(a_m);
233 nA_m = m_Vertices.size() - 1;
234 }
235 else
236 {
237 nA_m = nIndex;
238 }
239
240 nIndex = findVertex(b_m, 0.01);
241
242 if (nIndex == -1)
243 {
244 m_Vertices.push_back(b_m);
245 nB_m = m_Vertices.size() - 1;
246 }
247 else
248 {
249 nB_m = nIndex;
250 }
251
252 nIndex = findVertex(c_m, 0.01);
253
254 if (nIndex == -1)
255 {
256 m_Vertices.push_back(c_m);
257 nC_m = m_Vertices.size() - 1;
258 }
259 else
260 {
261 nC_m = nIndex;
262 }
263
264 // Create new faces with orig vertices plus midpoints
265 Face f[4];
266 f[0].set(nA, nA_m, nC_m);
267 f[1].set(nA_m, nB, nB_m);
268 f[2].set(nC_m, nB_m, nC);
269 f[3].set(nA_m, nB_m, nC_m);
270
271 for (int i = 0; i < 4; i++)
272 {
273 faces.push_back(f[i]);
274 }
275 }
276
277 // assign new faces
278 m_Faces = faces;
279}
280
281void
282CGraphGenerator::projectToSphere(float fRadius)
283{
284 TSphereCoord coord;
285 Vec3d point;
286 coord.fDistance = 1.0f;
287
288 for (int v = 0; v < int(m_Vertices.size()); v++)
289 {
290 float X = m_Vertices.at(v).x;
291 float Y = m_Vertices.at(v).y;
292 float Z = m_Vertices.at(v).z;
293
294 float x, y, z;
295
296 // Convert Cartesian X,Y,Z to spherical (radians)
297 float theta = atan2(Y, X);
298 float phi = atan2(sqrt(X * X + Y * Y), Z);
299
300 // Recalculate X,Y,Z for constant r, given theta & phi.
301 x = fRadius * sin(phi) * cos(theta);
302 y = fRadius * sin(phi) * sin(theta);
303 z = fRadius * cos(phi);
304
305 m_Vertices.at(v).x = x;
306 m_Vertices.at(v).y = y;
307 m_Vertices.at(v).z = z;
308 }
309}
310
311void
312CGraphGenerator::buildNodesAndEdges(CSphericalGraph* pGraph)
313{
314 // add nodes
315 TSphereCoord coord;
316
317 for (int v = 0; v < int(m_Vertices.size()); v++)
318 {
319 // printf("Vertex: %f,%f,%f\n", m_Vertices.at(v).x, m_Vertices.at(v).y, m_Vertices.at(v).z);
320 MathTools::convert(m_Vertices.at(v), coord);
321 CSGNode* pNode = pGraph->getNewNode();
322 pNode->setPosition(coord);
323 pGraph->addNode(pNode);
324 }
325
326 // add edges
327 // go through all faces (assumes check for duplicate edges in spherical graph!?)
328 for (int f = 0; f < int(m_Faces.size()); f++)
329 {
330 // printf(" %d,%d,%d\n", m_Faces.at(f).m_n1, m_Faces.at(f).m_n2, m_Faces.at(f).m_n3);
331 pGraph->addEdge(m_Faces.at(f).m_n1, m_Faces.at(f).m_n2);
332 pGraph->addEdge(m_Faces.at(f).m_n2, m_Faces.at(f).m_n3);
333 pGraph->addEdge(m_Faces.at(f).m_n3, m_Faces.at(f).m_n1);
334 }
335}
336
337int
338CGraphGenerator::findVertex(Vec3d position, float fEpsilon)
339{
340 float fDistance;
341 float fMinDistance = FLT_MAX;
342 int nIndex = -1;
343
344 for (int v = 0; v < int(m_Vertices.size()); v++)
345 {
346 fDistance = Math3d::Angle(position, m_Vertices.at(v));
347
348 if (fDistance < fMinDistance)
349 {
350 fMinDistance = fDistance;
351 nIndex = v;
352 }
353 }
354
355 if (fMinDistance > fEpsilon)
356 {
357 nIndex = -1;
358 }
359
360 return nIndex;
361}
EPolyhedronType
@ eOctahedron
@ eTetrahedron
@ eIcosahedron
constexpr T c
static void generateGraph(CSphericalGraph *pPlainGraph, EPolyhedronType nBaseType, int nLevels, float fRadius)
void setPosition(TSphereCoord position)
int addEdge(int nIndex1, int nIndex2)
int addNode(CSGNode *pNode)
virtual CSGNode * getNewNode()
void set(int n1, int n2, int n3)
static void convert(TSphereCoord in, Eigen::Vector3d &out)
VectorXD< 3, double > Vec3d
Definition VectorXD.h:737
VectorXD< D, T > sqrt(const VectorXD< D, T > &a)
Definition VectorXD.h:704
double a(double t, double a0, double j)
Definition CtrlUtil.h:45
double v(double t, double v0, double a0, double j)
Definition CtrlUtil.h:39
float fDistance
Definition Structs.h:25