35 const size_t nSubdivisions)
const {
39 for(
size_t i = 0; i < nSubdivisions; i++) {
40 nVertices += (nTriangles * 3) / 2;
41 nTriangles = nTriangles * 4;
50 template <
typename DT,
typename IT>
57 const size_t &icosphereIndex,
58 const size_t &nVerticesPerIcosphere,
59 const size_t &nTrianglesPerIcosphere,
60 const DT *centers)
const;
65 template <
typename DT,
typename IT>
72 const size_t &nSubdivisions)
const;
77 template <
typename DT,
typename IT>
84 const size_t &nSpheres,
85 const size_t &nSubdivisions,
90 DT *normals =
nullptr)
const;
98 template <
typename DT,
typename IT>
99 IT addVertex(
const DT &x,
103 IT &vertexIndex)
const {
104 IT cIndex = vertexIndex * 3;
106 DT length = std::sqrt(x * x + y * y + z * z);
107 vertexCoords[cIndex] = x / length;
108 vertexCoords[cIndex + 1] = y / length;
109 vertexCoords[cIndex + 2] = z / length;
111 return vertexIndex++;
120 IT addTriangle(
const IT &i,
123 IT *connectivityList,
124 IT &triangleIndex)
const {
125 IT cIndex = triangleIndex * 3;
126 connectivityList[cIndex + 0] = i;
127 connectivityList[cIndex + 1] = j;
128 connectivityList[cIndex + 2] = k;
129 return triangleIndex++;
138 template <
typename DT,
typename IT>
142 std::unordered_map<std::pair<IT, IT>, IT, boost::hash<std::pair<IT, IT>>>
145 IT &vertexIndex)
const {
146 bool const firstIsSmaller = i < j;
147 IT a = firstIsSmaller ? i : j;
148 IT b = firstIsSmaller ? j : i;
152 auto it = processedEdges.find({a, b});
153 if(it != processedEdges.end())
161 DT mx = (vertexCoords[aOffset] + vertexCoords[bOffset]) / 2.0;
162 DT my = (vertexCoords[aOffset + 1] + vertexCoords[bOffset + 1]) / 2.0;
163 DT mz = (vertexCoords[aOffset + 2] + vertexCoords[bOffset + 2]) / 2.0;
166 = this->addVertex<DT, IT>(mx, my, mz, vertexCoords, vertexIndex);
167 processedEdges.insert({{a, b}, mIndex});
178 IT *connectivityList,
181 const size_t &nSubdivisions)
const {
187 const std::string msg
188 =
"Computing Icosphere (S: " + std::to_string(nSubdivisions) +
")";
192 IT triangleIndex = 0;
197 DT t = (1.0 + sqrt(5.0)) / 2.0;
198 this->addVertex<DT, IT>(-1, t, 0, vertexCoords, vertexIndex);
199 this->addVertex<DT, IT>(1, t, 0, vertexCoords, vertexIndex);
200 this->addVertex<DT, IT>(-1, -t, 0, vertexCoords, vertexIndex);
201 this->addVertex<DT, IT>(1, -t, 0, vertexCoords, vertexIndex);
203 this->addVertex<DT, IT>(0, -1, t, vertexCoords, vertexIndex);
204 this->addVertex<DT, IT>(0, 1, t, vertexCoords, vertexIndex);
205 this->addVertex<DT, IT>(0, -1, -t, vertexCoords, vertexIndex);
206 this->addVertex<DT, IT>(0, 1, -t, vertexCoords, vertexIndex);
208 this->addVertex<DT, IT>(t, 0, -1, vertexCoords, vertexIndex);
209 this->addVertex<DT, IT>(t, 0, 1, vertexCoords, vertexIndex);
210 this->addVertex<DT, IT>(-t, 0, -1, vertexCoords, vertexIndex);
211 this->addVertex<DT, IT>(-t, 0, 1, vertexCoords, vertexIndex);
214 this->addTriangle<IT>(0, 11, 5, connectivityList, triangleIndex);
215 this->addTriangle<IT>(0, 5, 1, connectivityList, triangleIndex);
216 this->addTriangle<IT>(0, 1, 7, connectivityList, triangleIndex);
217 this->addTriangle<IT>(0, 7, 10, connectivityList, triangleIndex);
218 this->addTriangle<IT>(0, 10, 11, connectivityList, triangleIndex);
219 this->addTriangle<IT>(1, 5, 9, connectivityList, triangleIndex);
220 this->addTriangle<IT>(5, 11, 4, connectivityList, triangleIndex);
221 this->addTriangle<IT>(11, 10, 2, connectivityList, triangleIndex);
222 this->addTriangle<IT>(10, 7, 6, connectivityList, triangleIndex);
223 this->addTriangle<IT>(7, 1, 8, connectivityList, triangleIndex);
224 this->addTriangle<IT>(3, 9, 4, connectivityList, triangleIndex);
225 this->addTriangle<IT>(3, 4, 2, connectivityList, triangleIndex);
226 this->addTriangle<IT>(3, 2, 6, connectivityList, triangleIndex);
227 this->addTriangle<IT>(3, 6, 8, connectivityList, triangleIndex);
228 this->addTriangle<IT>(3, 8, 9, connectivityList, triangleIndex);
229 this->addTriangle<IT>(4, 9, 5, connectivityList, triangleIndex);
230 this->addTriangle<IT>(2, 4, 11, connectivityList, triangleIndex);
231 this->addTriangle<IT>(6, 2, 10, connectivityList, triangleIndex);
232 this->addTriangle<IT>(8, 6, 7, connectivityList, triangleIndex);
233 this->addTriangle<IT>(9, 8, 1, connectivityList, triangleIndex);
237 if(nSubdivisions > 0) {
239 size_t nVertices = 0;
240 size_t nTriangles = 0;
242 nVertices, nTriangles, nSubdivisions);
244 std::vector<IT> connectivityListTemp(nTriangles * 3, 0);
247 std::unordered_map<std::pair<IT, IT>, IT, boost::hash<std::pair<IT, IT>>>
251 for(
size_t s = 0; s < nSubdivisions; s++) {
254 = s % 2 == 0 ? connectivityList : connectivityListTemp.data();
255 IT *newList = s % 2 != 0 ? connectivityList : connectivityListTemp.data();
258 const size_t nOldTriangles = triangleIndex;
261 for(
size_t i = 0; i < nOldTriangles; i++) {
262 const IT offset = i * 3;
266 = this->addMidVertex(oldList[offset + 0], oldList[offset + 1],
267 processedEdges, vertexCoords, vertexIndex);
269 = this->addMidVertex(oldList[offset + 1], oldList[offset + 2],
270 processedEdges, vertexCoords, vertexIndex);
272 = this->addMidVertex(oldList[offset + 2], oldList[offset + 0],
273 processedEdges, vertexCoords, vertexIndex);
276 this->addTriangle(oldList[offset + 0], a, c, newList, triangleIndex);
277 this->addTriangle(oldList[offset + 1], b, a, newList, triangleIndex);
278 this->addTriangle(oldList[offset + 2], c, b, newList, triangleIndex);
279 this->addTriangle(a, b, c, newList, triangleIndex);
288 if(nSubdivisions > 0 && nSubdivisions % 2 != 0) {
289 size_t const n = nTriangles * 3;
290 for(
size_t i = 0; i < n; i++)
291 connectivityList[i] = connectivityListTemp[i];
340 IT *connectivityList,
343 const size_t &nSpheres,
344 const size_t &nSubdivisions,
352 this->printWrn(
"Number of input points smaller than 1.");
357 size_t nVerticesPerIcosphere, nTrianglesPerIcosphere;
358 if(!this->computeNumberOfVerticesAndTriangles(
359 nVerticesPerIcosphere, nTrianglesPerIcosphere, nSubdivisions))
363 if(!this->computeIcosphere(vertexCoords, connectivityList, nSubdivisions))
367 if(normals !=
nullptr) {
369 this->
printMsg(
"Computing Normals", 0, 0, this->threadNumber_,
372#ifdef TTK_ENABLE_OPENMP
373#pragma omp parallel for num_threads(threadNumber_)
375 for(
size_t i = 0; i < nSpheres; i++) {
376 size_t const n = nVerticesPerIcosphere * 3;
377 size_t offset = i * n;
378 for(
size_t j = 0; j < n; j++)
379 normals[offset++] = vertexCoords[j];
387 const std::string transMsg =
"Moving " + std::to_string(nSpheres)
388 +
" Icospheres (R: " + std::to_string(radius)
395 for(
size_t i = 0, j = nVerticesPerIcosphere * 3; i < j; i++) {
396 vertexCoords[i] *= radius;
399#ifdef TTK_ENABLE_OPENMP
400#pragma omp parallel for num_threads(threadNumber_)
402 for(
size_t i = 1; i < nSpheres; i++) {
403 this->translateIcosphere(vertexCoords, connectivityList, i,
404 nVerticesPerIcosphere, nTrianglesPerIcosphere,
409 this->translateIcosphere(vertexCoords, connectivityList, 0,
410 nVerticesPerIcosphere, nTrianglesPerIcosphere,