DistanceProxy.hpp
Go to the documentation of this file.
1 /*
2  * Original work Copyright (c) 2006-2009 Erin Catto http://www.box2d.org
3  * Modified work Copyright (c) 2017 Louis Langholtz https://github.com/louis-langholtz/PlayRho
4  *
5  * This software is provided 'as-is', without any express or implied
6  * warranty. In no event will the authors be held liable for any damages
7  * arising from the use of this software.
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  * 1. The origin of this software must not be misrepresented; you must not
12  * claim that you wrote the original software. If you use this software
13  * in a product, an acknowledgment in the product documentation would be
14  * appreciated but is not required.
15  * 2. Altered source versions must be plainly marked as such, and must not be
16  * misrepresented as being the original software.
17  * 3. This notice may not be removed or altered from any source distribution.
18  */
19 
20 #ifndef PLAYRHO_COLLISION_DISTANCEPROXY_HPP
21 #define PLAYRHO_COLLISION_DISTANCEPROXY_HPP
22 
23 #include <PlayRho/Common/Math.hpp>
24 #include <PlayRho/Common/Range.hpp>
25 #include <vector>
26 #include <algorithm>
27 
28 // Define IMPLEMENT_DISTANCEPROXY_WITH_BUFFERS to implement the DistanceProxy class
29 // using buffers instead of pointers. Note that timing tests suggest implementing with
30 // buffers is significantly slower. Using buffers could make defining new shapes
31 // easier though so a buffering code alternative is kept in the source code for now.
32 // #define IMPLEMENT_DISTANCEPROXY_WITH_BUFFERS
33 
34 namespace playrho {
35 namespace d2 {
36 
37  class Shape;
38 
52  {
53  public:
55  using ConstVertexPointer = const Length2*;
56 
59 
61  using ConstNormalPointer = const UnitVec*;
62 
65 
66  DistanceProxy() = default;
67 
69  DistanceProxy(const DistanceProxy& copy) noexcept:
70 #ifndef IMPLEMENT_DISTANCEPROXY_WITH_BUFFERS
71  m_vertices{copy.m_vertices},
72  m_normals{copy.m_normals},
73 #endif
74  m_count{copy.m_count},
75  m_vertexRadius{copy.m_vertexRadius}
76  {
77 #ifdef IMPLEMENT_DISTANCEPROXY_WITH_BUFFERS
78  const auto count = copy.m_count;
79  std::copy(copy.m_vertices, copy.m_vertices + count, m_vertices);
80  std::copy(copy.m_normals, copy.m_normals + count, m_normals);
81 #else
82  // Intentionall empty.
83 #endif
84  }
85 
104  DistanceProxy(const NonNegative<Length> vertexRadius, const VertexCounter count,
105  const Length2* vertices, const UnitVec* normals) noexcept:
106 #ifndef IMPLEMENT_DISTANCEPROXY_WITH_BUFFERS
107  m_vertices{vertices},
108  m_normals{normals},
109 #endif
110  m_count{count},
111  m_vertexRadius{vertexRadius}
112  {
113  assert(vertexRadius >= 0_m);
114  assert(count >= 0);
115  assert(count < 1 || vertices);
116  assert(count < 2 || normals);
117 #ifdef IMPLEMENT_DISTANCEPROXY_WITH_BUFFERS
118  if (vertices)
119  {
120  std::copy(vertices, vertices + count, m_vertices);
121  }
122  if (normals)
123  {
124  std::copy(normals, normals + count, m_normals);
125  }
126 #endif
127  }
128 
131  auto GetVertexRadius() const noexcept { return m_vertexRadius; }
132 
135  {
136  return {m_vertices, m_vertices + m_count};
137  }
138 
141  {
142  return {m_normals, m_normals + m_count};
143  }
144 
149  auto GetVertexCount() const noexcept { return m_count; }
150 
164  auto GetVertex(VertexCounter index) const noexcept
165  {
166  assert(index != InvalidVertex);
167  assert(index < m_count);
168  return *(m_vertices + index);
169  }
170 
172  auto GetNormal(VertexCounter index) const noexcept
173  {
174  assert(index != InvalidVertex);
175  assert(index < m_count);
176  return *(m_normals + index);
177  }
178 
179  private:
180 #ifdef IMPLEMENT_DISTANCEPROXY_WITH_BUFFERS
181  Length2 m_vertices[MaxShapeVertices];
182  UnitVec m_normals[MaxShapeVertices];
183 #else
184  const Length2* m_vertices = nullptr;
185  const UnitVec* m_normals = nullptr;
186 #endif
187  VertexCounter m_count = 0;
188  NonNegative<Length> m_vertexRadius = 0_m;
189  };
190 
191  // Free functions...
192 
195  bool operator== (const DistanceProxy& lhs, const DistanceProxy& rhs) noexcept;
196 
199  inline bool operator!= (const DistanceProxy& lhs, const DistanceProxy& rhs) noexcept
200  {
201  return !(lhs == rhs);
202  }
203 
206  {
207  return arg.GetVertexRadius();
208  }
209 
220  template <class T>
221  inline VertexCounter GetSupportIndex(const DistanceProxy& proxy, T dir) noexcept
222  {
223  using VT = typename T::value_type;
224  using OT = decltype(VT{} * 0_m);
225 
226  auto index = InvalidVertex; // Index of vertex that when dotted with dir has the max value.
227  auto maxValue = -std::numeric_limits<OT>::infinity(); // Max dot value.
228  auto i = VertexCounter{0};
229  for (const auto& vertex: proxy.GetVertices())
230  {
231  const auto value = Dot(vertex, dir);
232  if (maxValue < value)
233  {
234  maxValue = value;
235  index = i;
236  }
237  ++i;
238  }
239  return index;
240  }
241 
243  std::size_t FindLowestRightMostVertex(Span<const Length2> vertices);
244 
246  std::vector<Length2> GetConvexHullAsVector(Span<const Length2> vertices);
247 
254  bool TestPoint(const DistanceProxy& proxy, Length2 point) noexcept;
255 
256 } // namespace d2
257 } // namespace playrho
258 
259 #endif // PLAYRHO_COLLISION_DISTANCEPROXY_HPP