MultiShapeConf.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Louis Langholtz https://github.com/louis-langholtz/PlayRho
3  *
4  * This software is provided 'as-is', without any express or implied
5  * warranty. In no event will the authors be held liable for any damages
6  * arising from the use of this software.
7  *
8  * Permission is granted to anyone to use this software for any purpose,
9  * including commercial applications, and to alter it and redistribute it
10  * freely, subject to the following restrictions:
11  *
12  * 1. The origin of this software must not be misrepresented; you must not
13  * claim that you wrote the original software. If you use this software
14  * in a product, an acknowledgment in the product documentation would be
15  * appreciated but is not required.
16  * 2. Altered source versions must be plainly marked as such, and must not be
17  * misrepresented as being the original software.
18  * 3. This notice may not be removed or altered from any source distribution.
19  */
20 
23 #include <algorithm>
24 #include <iterator>
25 
26 namespace playrho {
27 namespace d2 {
28 
32 MassData GetMassData(const MultiShapeConf& arg) noexcept
33 {
34  auto mass = 0_kg;
35  const auto origin = Length2{};
36  auto weightedCenter = origin * Kilogram;
37  auto I = RotInertia{0};
38  const auto density = arg.density;
39 
40  std::for_each(begin(arg.children), end(arg.children),
41  [&](const ConvexHull& ch) {
42  const auto dp = ch.GetDistanceProxy();
43  const auto md = playrho::d2::GetMassData(ch.GetVertexRadius(), density,
44  Span<const Length2>(begin(dp.GetVertices()), dp.GetVertexCount()));
45  mass += Mass{md.mass};
46  weightedCenter += md.center * Mass{md.mass};
47  I += RotInertia{md.I};
48  });
49 
50  const auto center = (mass > 0_kg)? weightedCenter / mass: origin;
51  return MassData{center, mass, I};
52 }
53 
54 ConvexHull ConvexHull::Get(const VertexSet& pointSet, NonNegative<Length> vertexRadius)
55 {
56  auto vertices = GetConvexHullAsVector(pointSet);
57  assert(!empty(vertices) && size(vertices) < std::numeric_limits<VertexCounter>::max());
58 
59  const auto count = static_cast<VertexCounter>(size(vertices));
60 
61  auto normals = std::vector<UnitVec>();
62  if (count > 1)
63  {
64  // Compute normals.
65  for (auto i = decltype(count){0}; i < count; ++i)
66  {
67  const auto nextIndex = GetModuloNext(i, count);
68  const auto edge = vertices[nextIndex] - vertices[i];
69  normals.push_back(GetUnitVector(GetFwdPerpendicular(edge)));
70  }
71  }
72  else if (count == 1)
73  {
74  normals.push_back(UnitVec{});
75  }
76 
77  return ConvexHull{vertices, normals, vertexRadius};
78 }
79 
81 {
82  auto newPoints = VertexSet{};
83  // clang++ recommends the following loop variable 'v' be of reference type (instead of value).
84  for (const auto& v: vertices)
85  {
86  newPoints.add(m * v);
87  }
88  *this = Get(newPoints, vertexRadius);
89  return *this;
90 }
91 
92 MultiShapeConf& MultiShapeConf::AddConvexHull(const VertexSet& pointSet,
93  NonNegative<Length> vertexRadius) noexcept
94 {
95  children.emplace_back(ConvexHull::Get(pointSet, vertexRadius));
96  return *this;
97 }
98 
100 {
101  std::for_each(begin(children), end(children), [=](ConvexHull& child){
102  child.Transform(m);
103  });
104  return *this;
105 }
106 
107 } // namespace d2
108 } // namespace playrho