3 #include <vtestbed/config/real_type.hh> 4 #include <vtestbed/geometry/inertia_tensor.hh> 5 #include <vtestbed/geometry/line_segment.hh> 6 #include <vtestbed/geometry/math.hh> 7 #include <vtestbed/geometry/polygon.hh> 8 #include <vtestbed/geometry/polyline.hh> 12 template <
class T,
int N>
19 return (lhs.contains(rhs.front(), eps) && lhs.contains(rhs.back(), eps));
24 template <
class T,
int N>
28 auto& segments = *
this;
29 auto n = segments.size();
31 for (size_type i=0; i<n; ++i) {
32 for (size_type j=i+1; j<n; ++j) {
33 const auto& s1 = segments[i];
34 const auto& s2 = segments[j];
37 if (near(s1,s2,eps) || near(s1,s3,eps)
39 mask[i] =
true, mask[j] =
true;
43 for (size_type i=n; i>0; --i) {
46 segments.erase(segments.begin()+j);
51 template <
class T,
int N>
55 auto& segments = *
this;
56 auto n = segments.size();
58 for (size_type i=0; i<n; ++i) {
59 for (size_type j=0; j<n; ++j) {
60 if (i == j) {
continue; }
61 auto& s1 = segments[i];
62 const auto& s2 = segments[j];
63 if (near(s1.back(), s2.front(), eps) &&
64 Line_segment<T,N>(s1.front(), s2.back()).contains(s1.back(), eps)) {
65 s1.back() = s2.back();
66 segments.erase(segments.begin()+j);
74 template <
class T,
int N>
78 auto& segments = *
this;
79 auto n = segments.size();
80 if (n <= 3) {
return; }
82 auto p0 = std::max_element(
83 segments.begin(), segments.end(),
84 [] (const_reference lhs, const_reference rhs) {
86 return cmp(lhs.front(), rhs.front());
90 for (
const auto& s : segments) {
91 std::clog <<
"near(s.front(), s.back(), eps)=" << near(s.front(), s.back(), eps) << std::endl;
95 value_type candidate, orig;
98 std::clog <<
"convex_hull.size()=" << convex_hull.size() << std::endl;
99 for (size_type i=0; i<n; ++i) {
100 const auto& s = segments[i];
101 if (near(p0, s.front(), eps)) {
109 Vertex<T,N> v1 = s.back() - p0;
110 Vertex<T,N> v2 = candidate.back() - p0;
115 auto x1 = s.back()(0);
116 auto y1 = s.back()(1);
117 auto x2 = candidate.back()(0);
118 auto y2 = candidate.back()(1);
119 auto x3 = orig.back()(0);
120 auto y3 = orig.back()(1);
121 auto lhs = x2*y0 + x0*y1 + x1*y2;
122 auto rhs = x1*y0 + x2*y1 + x0*y2;
123 auto lhs2 = x3*y0 + x0*y1 + x1*y3;
124 auto rhs2 = x1*y0 + x3*y1 + x0*y3;
125 std::clog <<
"(lhs-rhs)=" << (lhs-rhs) << std::endl;
126 std::clog <<
"(lhs2-rhs2)=" << (lhs2-rhs2) << std::endl;
127 if (lhs2-rhs2 > diff) {
135 std::clog <<
"candidate=" << candidate << std::endl;
136 convex_hull.emplace_back(candidate);
137 segments.erase(segments.begin()+idx);
138 p0 = candidate.back();
139 }
while (!segments.empty() &&
140 !near(convex_hull.front().front(), convex_hull.back().back(), eps));
141 segments = std::move(convex_hull);
147 using T = VTB_REAL_TYPE;
148 Vertex<T,2> origin{T{}};
149 for (
const auto& segment : *
this) {
150 origin += segment[0];
151 origin += segment[1];
153 origin /= 2*this->size();
154 for (
auto& segment : *
this) {
155 auto d = det(origin, segment[0], segment[1]);
156 if (d < 0) { segment.flip(); }
160 template <
class T,
int N>
163 auto& segments = *
this;
164 const auto n = segments.size();
165 if (n <= 1) {
return; }
166 for (
size_t i=0; i<n; ++i) {
167 const auto& back = segments[i].back();
168 for (
size_t j=i+1; j<n; ++j) {
169 const auto& front = segments[j].front();
170 if (all(front == back)) {
171 if (j != i+1) { std::swap(segments[i+1], segments[j]); }
178 template <
class T,
int N>
182 for (
const auto& segment : *
this) {
183 result.emplace_back(segment.front());
188 template <
class T,
int N>
191 for (
const auto& segment : *
this) { segment.gnuplot(out); out <<
"\n\n"; }
194 template <
class T,
int N>
197 static const T mult[6] = {
199 T{1}/T{6}, T{1}/T{6},
200 T{1}/T{12}, T{1}/T{12},
204 for (
const auto& segment : polyline) {
205 const auto& v0 = segment.front();
206 const auto& v1 = segment.back();
207 auto x0 = v0(0), y0 = v0(1), x1 = v1(0), y1 = v1(1);
208 auto x0y1 = x0*y1, y0x1 = y0*x1;
209 auto cp = x0y1 - y0x1;
211 intg[1] += cp*(x0 + x1);
212 intg[2] += cp*(y0 + y1);
213 intg[3] += cp*(y0*y0 + y0*y1 + y1*y1);
214 intg[4] += cp*(x0*x0 + x0*x1 + x1*x1);
215 intg[5] += cp*(x0y1 + 2*x0*y0 + 2*x1*y1 + y0x1);
217 for (
int i=0; i<6; ++i) { intg[i] *= mult[i]; }
220 m.centre(0) = intg[1], m.centre(1) = intg[2];
221 if (m.mass != 0) { m.centre /= m.mass; }
223 m.inertia.xx = intg[3] - m.mass*cm(0)*cm(0);
224 m.inertia.yy = intg[4] - m.mass*cm(1)*cm(1);
225 m.inertia.xy = intg[5] - m.mass*cm(0)*cm(1);
Mass_moments< T, N > mass_moments(const Polyline< T, N > &polyline)
Calculate area, centroid and inertia tensor.
A polygon composed of line segments.
void gift_wrap()
Convex hull.