PolygonShapeConf.cpp
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 
22 
23 namespace playrho {
24 namespace d2 {
25 
27 
29  const PolygonShapeConf& conf) noexcept:
30  ShapeBuilder{conf}
31 {
32  SetAsBox(hx, hy);
33 }
34 
36  const PolygonShapeConf& conf) noexcept:
37  ShapeBuilder{conf}
38 {
39  Set(points);
40 }
41 
43 {
44  m_centroid = Length2{};
45 
46  // vertices must be counter-clockwise
47 
48  const auto btm_rgt = Length2{+hx, -hy};
49  const auto top_rgt = Length2{ hx, hy};
50  const auto top_lft = Length2{-hx, +hy};
51  const auto btm_lft = Length2{-hx, -hy};
52 
53  m_vertices.clear();
54  m_vertices.emplace_back(btm_rgt);
55  m_vertices.emplace_back(top_rgt);
56  m_vertices.emplace_back(top_lft);
57  m_vertices.emplace_back(btm_lft);
58 
59  m_normals.clear();
60  m_normals.emplace_back(UnitVec::GetRight());
61  m_normals.emplace_back(UnitVec::GetTop());
62  m_normals.emplace_back(UnitVec::GetLeft());
63  m_normals.emplace_back(UnitVec::GetBottom());
64 
65  return *this;
66 }
67 
69 PolygonShapeConf& PolygonShapeConf::UseVertices(const std::vector<Length2>& verts) noexcept
70 {
71  return Set(Span<const Length2>(data(verts), size(verts)));
72 }
73 
75  Length2 center, Angle angle) noexcept
76 {
77  SetAsBox(hx, hy);
78  Transform(Transformation{center, UnitVec::Get(angle)});
79  return *this;
80 }
81 
83 {
84  for (auto i = decltype(GetVertexCount()){0}; i < GetVertexCount(); ++i)
85  {
86  m_vertices[i] = playrho::d2::Transform(m_vertices[i], xfm);
87  m_normals[i] = Rotate(m_normals[i], xfm.q);
88  }
89  m_centroid = playrho::d2::Transform(m_centroid, xfm);
90  return *this;
91 }
92 
94 {
95  auto newPoints = VertexSet{};
96  // clang++ recommends the following loop variable 'v' be of reference type (instead of value).
97  for (const auto& v: m_vertices)
98  {
99  newPoints.add(m * v);
100  }
101  return Set(newPoints);
102 }
103 
105 {
106  // Perform welding and copy vertices into local buffer.
107  auto point_set = VertexSet(Square(DefaultLinearSlop));
108  for (auto&& p: points)
109  {
110  point_set.add(p);
111  }
112  return Set(point_set);
113 }
114 
116 {
117  m_vertices = GetConvexHullAsVector(points);
118  assert(size(m_vertices) < std::numeric_limits<VertexCounter>::max());
119 
120  const auto count = static_cast<VertexCounter>(size(m_vertices));
121 
122  m_normals.clear();
123  if (count > 1)
124  {
125  // Compute normals.
126  for (auto i = decltype(count){0}; i < count; ++i)
127  {
128  const auto edge = GetEdge(*this, i);
129  m_normals.emplace_back(GetUnitVector(GetFwdPerpendicular(edge)));
130  }
131  }
132  else if (count == 1)
133  {
134  m_normals.emplace_back(UnitVec{});
135  }
136 
137  // Compute the polygon centroid.
138  switch (count)
139  {
140  case 0:
141  m_centroid = GetInvalid<Length2>();
142  break;
143  case 1:
144  m_centroid = m_vertices[0];
145  break;
146  case 2:
147  m_centroid = (m_vertices[0] + m_vertices[1]) / Real{2};
148  break;
149  default:
150  m_centroid = ComputeCentroid(GetVertices());
151  break;
152  }
153 
154  return *this;
155 }
156 
158 {
159  assert(shape.GetVertexCount() > 1);
160 
161  const auto i0 = index;
162  const auto i1 = GetModuloNext(index, shape.GetVertexCount());
163  return shape.GetVertex(i1) - shape.GetVertex(i0);
164 }
165 
167 {
168  const auto count = size(verts);
169  for (auto i = decltype(count){0}; i < count; ++i)
170  {
171  const auto i1 = i;
172  const auto i2 = GetModuloNext(i1, count);
173  const auto p = verts[i1];
174  const auto e = verts[i2] - p;
175  for (auto j = decltype(count){0}; j < count; ++j)
176  {
177  if ((j == i1) || (j == i2))
178  {
179  continue;
180  }
181  const auto v = verts[j] - p;
182  const auto c = Cross(e, v);
183  if (c < 0_m2)
184  {
185  return false;
186  }
187  }
188  }
189  return true;
190 }
191 
192 } // namespace d2
193 } // namespace playrho