DART 6.11.1
Loading...
Searching...
No Matches
Icosphere-impl.hpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2011-2021, The DART development contributors
3 * All rights reserved.
4 *
5 * The list of contributors can be found at:
6 * https://github.com/dartsim/dart/blob/master/LICENSE
7 *
8 * This file is provided under the following "BSD-style" License:
9 * Redistribution and use in source and binary forms, with or
10 * without modification, are permitted provided that the following
11 * conditions are met:
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer in the documentation and/or other materials provided
17 * with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
34
35#include <array>
36
38
39namespace dart {
40namespace math {
41
42//==============================================================================
43template <typename S>
45{
46 std::size_t numVertices = 12;
47 for (auto i = 0u; i < subdivisions; ++i)
48 numVertices += getNumEdges(i);
49 return numVertices;
50}
51
52//==============================================================================
53template <typename S>
55{
56 return getNumTriangles(subdivisions) / 2 * 3;
57}
58
59//==============================================================================
60template <typename S>
62{
63 return 20 * std::pow(4, subdivisions);
64}
65
66//==============================================================================
67template <typename S>
68std::pair<typename Icosphere<S>::Vertices, typename Icosphere<S>::Triangles>
70{
71 constexpr S phi = constants<S>::phi();
72 const S unitX = 1 / std::sqrt(1 + phi * phi);
73 const S unitZ = unitX * phi;
74
75 const S x = radius * unitX;
76 const S z = radius * unitZ;
77
78 std::vector<Vector3> vertices = {{{-x, 0, z},
79 {x, 0, z},
80 {-x, 0, -z},
81 {x, 0, -z},
82 {0, z, x},
83 {0, z, -x},
84 {0, -z, x},
85 {0, -z, -x},
86 {z, x, 0},
87 {-z, x, 0},
88 {z, -x, 0},
89 {-z, -x, 0}}};
90
91 static std::vector<Triangle> triangles
92 = {{{0, 4, 1}, {0, 9, 4}, {9, 5, 4}, {4, 5, 8}, {4, 8, 1},
93 {8, 10, 1}, {8, 3, 10}, {5, 3, 8}, {5, 2, 3}, {2, 7, 3},
94 {7, 10, 3}, {7, 6, 10}, {7, 11, 6}, {11, 0, 6}, {0, 1, 6},
95 {6, 1, 10}, {9, 0, 11}, {9, 11, 2}, {9, 2, 5}, {7, 2, 11}}};
96
97 return std::make_pair(vertices, triangles);
98}
99
100//==============================================================================
101template <typename S>
103 : mRadius(radius), mSubdivisions(subdivisions)
104{
105 static_assert(
106 std::is_floating_point<S>::value,
107 "Scalar must be a floating point type.");
108 assert(radius > 0);
109
110 build();
111}
112
113//==============================================================================
114template <typename S>
116{
117 return mRadius;
118}
119
120//==============================================================================
121template <typename S>
123{
124 return mSubdivisions;
125}
126
127//==============================================================================
128template <typename S>
130{
131 // Reference: https://schneide.blog/2016/07/15/generating-an-icosphere-in-c/
132
133 // Create icosahedron
134 std::tie(this->mVertices, this->mTriangles) = computeIcosahedron(mRadius);
135
136 // Return if no need to subdivide
137 if (mSubdivisions == 0)
138 return;
139
140 // Create index map that is used for subdivision
141 using IndexMap = std::map<std::pair<std::size_t, std::size_t>, std::size_t>;
142 IndexMap midVertexIndices;
143
144 // Create a temporary array of faces that is used for subdivision
145 std::vector<Triangle> tmpFaces;
146 if (mSubdivisions % 2)
147 {
148 this->mTriangles.reserve(getNumTriangles(mSubdivisions - 1));
149 tmpFaces.reserve(getNumTriangles(mSubdivisions));
150 }
151 else
152 {
153 this->mTriangles.reserve(getNumTriangles(mSubdivisions));
154 tmpFaces.reserve(getNumTriangles(mSubdivisions - 1));
155 }
156
157 // Create more intermediate variables that are used for subdivision
158 std::vector<Triangle>* currFaces = &(this->mTriangles);
159 std::vector<Triangle>* newFaces = &tmpFaces;
160 std::array<std::size_t, 3> mid;
161
162 // Subdivide icosahedron/icosphere iteratively. The key is to not duplicate
163 // the newly created vertices and faces during each subdivision.
164 for (std::size_t i = 0; i < mSubdivisions; ++i)
165 {
166 // Clear the array of faces that will store the faces of the subdivided
167 // isosphere in this iteration. This is because the faces of the previous
168 // isosphere are not reused.
169 (*newFaces).clear();
170 midVertexIndices.clear();
171
172 // Iterate each face of the previous icosphere and divide the face into
173 // four new faces.
174 for (std::size_t j = 0; j < (*currFaces).size(); ++j)
175 {
176 const auto& outter = (*currFaces)[j];
177
178 // Create vertices on the middle of edges if not already created.
179 for (std::size_t k = 0; k < 3; ++k)
180 {
181 auto indexA = outter[k];
182 auto indexB = outter[(k + 1) % 3];
183
184 // Sort indices to guarantee that the key is unique for the same pairs
185 // of indices.
186 if (indexA > indexB)
187 std::swap(indexA, indexB);
188
189 // Check whether the mid vertex given index pair is already created.
190 const auto result = midVertexIndices.insert(
191 {{indexA, indexB}, this->mVertices.size()});
192 const auto& inserted = result.second;
193 if (inserted)
194 {
195 // Create a vertex on the middle of the edge where the length of the
196 // vertex is equal to the radius of the icosphere.
197 const auto& v1 = this->mVertices[indexA];
198 const auto& v2 = this->mVertices[indexB];
199 this->mVertices.emplace_back(mRadius * (v1 + v2).normalized());
200 }
201
202 mid[k] = result.first->second;
203 }
204
205 // Add four new faces.
206 (*newFaces).emplace_back(Triangle(outter[0], mid[0], mid[2]));
207 (*newFaces).emplace_back(Triangle(mid[0], outter[1], mid[1]));
208 (*newFaces).emplace_back(Triangle(mid[0], mid[1], mid[2]));
209 (*newFaces).emplace_back(Triangle(mid[2], mid[1], outter[2]));
210 }
211
212 // Swap the arrays of faces.
213 std::swap(currFaces, newFaces);
214 }
215
216 // Assign faces if needed.
217 this->mTriangles = *currFaces;
218}
219
220} // namespace math
221} // namespace dart
CollisionResult * result
Collision result of DART.
Definition FCLCollisionDetector.cpp:160
S_ S
Definition Icosphere.hpp:53
std::size_t getNumSubdivisions() const
Returns the number of subdivisions of the icosphere.
Definition Icosphere-impl.hpp:122
typename Base::Vector3 Vector3
Definition Icosphere.hpp:56
static std::size_t getNumVertices(std::size_t subdivisions)
Returns the number of vertices of icosphere given subdivisions.
Definition Icosphere-impl.hpp:44
static std::size_t getNumEdges(std::size_t subdivisions)
Returns the number of edges of icosphere given subdivisions.
Definition Icosphere-impl.hpp:54
std::vector< Triangle > Triangles
Definition Icosphere.hpp:60
S getRadius() const
Returns the radius of the icosphere.
Definition Icosphere-impl.hpp:115
static std::pair< Vertices, Triangles > computeIcosahedron(S radius)
Returns vertices and faces of icosahedron given radius.
Definition Icosphere-impl.hpp:69
typename Base::Triangle Triangle
Definition Icosphere.hpp:57
Icosphere(S radius, std::size_t subdivisions)
Construct an icosphere given radius and subdivisions.
Definition Icosphere-impl.hpp:102
void build()
Internal function to build icosphere given radius and subdivisions.
Definition Icosphere-impl.hpp:129
static std::size_t getNumTriangles(std::size_t subdivisions)
Returns the number of triangles of icosphere given subdivisions.
Definition Icosphere-impl.hpp:61
Definition BulletCollisionDetector.cpp:65
static constexpr T phi()
The golden ratio.
Definition Constants.hpp:63