DART 6.12.2
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
33#include <array>
34
37
38namespace dart {
39namespace math {
40
41//==============================================================================
42template <typename S>
44{
45 std::size_t numVertices = 12;
46 for (auto i = 0u; i < subdivisions; ++i)
47 numVertices += getNumEdges(i);
48 return numVertices;
49}
50
51//==============================================================================
52template <typename S>
54{
55 return getNumTriangles(subdivisions) / 2 * 3;
56}
57
58//==============================================================================
59template <typename S>
61{
62 return 20 * std::pow(4, subdivisions);
63}
64
65//==============================================================================
66template <typename S>
67std::pair<typename Icosphere<S>::Vertices, typename Icosphere<S>::Triangles>
69{
70 constexpr S phi = constants<S>::phi();
71 const S unitX = 1 / std::sqrt(1 + phi * phi);
72 const S unitZ = unitX * phi;
73
74 const S x = radius * unitX;
75 const S z = radius * unitZ;
76
77 std::vector<Vector3> vertices = {{-x, 0, z},
78 {x, 0, z},
79 {-x, 0, -z},
80 {x, 0, -z},
81 {0, z, x},
82 {0, z, -x},
83 {0, -z, x},
84 {0, -z, -x},
85 {z, x, 0},
86 {-z, x, 0},
87 {z, -x, 0},
88 {-z, -x, 0}};
89
90 static std::vector<Triangle> triangles
91 = {{0, 4, 1}, {0, 9, 4}, {9, 5, 4}, {4, 5, 8}, {4, 8, 1},
92 {8, 10, 1}, {8, 3, 10}, {5, 3, 8}, {5, 2, 3}, {2, 7, 3},
93 {7, 10, 3}, {7, 6, 10}, {7, 11, 6}, {11, 0, 6}, {0, 1, 6},
94 {6, 1, 10}, {9, 0, 11}, {9, 11, 2}, {9, 2, 5}, {7, 2, 11}};
95
96 return std::make_pair(vertices, triangles);
97}
98
99//==============================================================================
100template <typename S>
102 : mRadius(radius), mSubdivisions(subdivisions)
103{
104 static_assert(
105 std::is_floating_point<S>::value,
106 "Scalar must be a floating point type.");
107 assert(radius > 0);
108
109 build();
110}
111
112//==============================================================================
113template <typename S>
115{
116 return mRadius;
117}
118
119//==============================================================================
120template <typename S>
122{
123 return mSubdivisions;
124}
125
126//==============================================================================
127template <typename S>
129{
130 // Reference: https://schneide.blog/2016/07/15/generating-an-icosphere-in-c/
131
132 // Create icosahedron
133 std::tie(this->mVertices, this->mTriangles) = computeIcosahedron(mRadius);
134
135 // Return if no need to subdivide
136 if (mSubdivisions == 0)
137 return;
138
139 // Create index map that is used for subdivision
140 using IndexMap = std::map<std::pair<std::size_t, std::size_t>, std::size_t>;
141 IndexMap midVertexIndices;
142
143 // Create a temporary array of faces that is used for subdivision
144 std::vector<Triangle> tmpFaces;
145 if (mSubdivisions % 2)
146 {
147 this->mTriangles.reserve(getNumTriangles(mSubdivisions - 1));
148 tmpFaces.reserve(getNumTriangles(mSubdivisions));
149 }
150 else
151 {
152 this->mTriangles.reserve(getNumTriangles(mSubdivisions));
153 tmpFaces.reserve(getNumTriangles(mSubdivisions - 1));
154 }
155
156 // Create more intermediate variables that are used for subdivision
157 std::vector<Triangle>* currFaces = &(this->mTriangles);
158 std::vector<Triangle>* newFaces = &tmpFaces;
159 std::array<std::size_t, 3> mid;
160
161 // Subdivide icosahedron/icosphere iteratively. The key is to not duplicate
162 // the newly created vertices and faces during each subdivision.
163 for (std::size_t i = 0; i < mSubdivisions; ++i)
164 {
165 // Clear the array of faces that will store the faces of the subdivided
166 // isosphere in this iteration. This is because the faces of the previous
167 // isosphere are not reused.
168 (*newFaces).clear();
169 midVertexIndices.clear();
170
171 // Iterate each face of the previous icosphere and divide the face into
172 // four new faces.
173 for (std::size_t j = 0; j < (*currFaces).size(); ++j)
174 {
175 const auto& outter = (*currFaces)[j];
176
177 // Create vertices on the middle of edges if not already created.
178 for (std::size_t k = 0; k < 3; ++k)
179 {
180 auto indexA = outter[k];
181 auto indexB = outter[(k + 1) % 3];
182
183 // Sort indices to guarantee that the key is unique for the same pairs
184 // of indices.
185 if (indexA > indexB)
186 std::swap(indexA, indexB);
187
188 // Check whether the mid vertex given index pair is already created.
189 const auto result = midVertexIndices.insert(
190 {{indexA, indexB}, this->mVertices.size()});
191 const auto& inserted = result.second;
192 if (inserted)
193 {
194 // Create a vertex on the middle of the edge where the length of the
195 // vertex is equal to the radius of the icosphere.
196 const auto& v1 = this->mVertices[indexA];
197 const auto& v2 = this->mVertices[indexB];
198 this->mVertices.emplace_back(mRadius * (v1 + v2).normalized());
199 }
200
201 mid[k] = result.first->second;
202 }
203
204 // Add four new faces.
205 (*newFaces).emplace_back(Triangle(outter[0], mid[0], mid[2]));
206 (*newFaces).emplace_back(Triangle(mid[0], outter[1], mid[1]));
207 (*newFaces).emplace_back(Triangle(mid[0], mid[1], mid[2]));
208 (*newFaces).emplace_back(Triangle(mid[2], mid[1], outter[2]));
209 }
210
211 // Swap the arrays of faces.
212 std::swap(currFaces, newFaces);
213 }
214
215 // Assign faces if needed.
216 this->mTriangles = *currFaces;
217}
218
219} // namespace math
220} // 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:121
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:43
static std::size_t getNumEdges(std::size_t subdivisions)
Returns the number of edges of icosphere given subdivisions.
Definition Icosphere-impl.hpp:53
std::vector< Triangle > Triangles
Definition Icosphere.hpp:60
S getRadius() const
Returns the radius of the icosphere.
Definition Icosphere-impl.hpp:114
static std::pair< Vertices, Triangles > computeIcosahedron(S radius)
Returns vertices and faces of icosahedron given radius.
Definition Icosphere-impl.hpp:68
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:101
void build()
Internal function to build icosphere given radius and subdivisions.
Definition Icosphere-impl.hpp:128
static std::size_t getNumTriangles(std::size_t subdivisions)
Returns the number of triangles of icosphere given subdivisions.
Definition Icosphere-impl.hpp:60
Definition BulletCollisionDetector.cpp:60
static constexpr T phi()
The golden ratio.
Definition Constants.hpp:62