14 #include "GmshConfig.h"
20 #if defined(HAVE_MESH)
25 : center({{0.0, 0.0}}), size({{0.0, 0.0}}), axisX({{0.0, 0.0}}),
34 double dx = 0.5 *
size[0];
35 double dy = 0.5 *
size[1];
36 double dz = 0.5 *
size[2];
82 double sizeY,
double sizeZ,
112 case 0: ret =
axisX;
break;
113 case 1: ret =
axisY;
break;
114 case 2: ret =
axisZ;
break;
122 for(
int i = 0; i < 3; i++) {
124 collide_axes[i + 3] = obb.
getAxis(i);
131 for(std::size_t i = 0; i < 3; i++) {
132 for(std::size_t j = 3; j < 6; j++) {
133 collide_axes[3 * i + j + 3] =
crossprod(collide_axes[i], collide_axes[j]);
138 for(std::size_t i = 0; i < 15; i++) {
140 for(std::size_t j = 0; j < 6; j++) {
141 val += 0.5 * (sizes[j < 3 ? 0 : 1])(j % 3) *
142 std::abs(
dot(collide_axes[j], collide_axes[i]));
144 if(std::abs(
dot(collide_axes[i], T)) > val) {
return false; }
152 #if defined(HAVE_MESH)
154 int num_vertices = vertices.
size();
157 std::set<SPoint3> unique;
158 unique.insert(vertices.begin(), vertices.end());
160 num_vertices = unique.size();
172 for(
auto uIter = unique.begin(); uIter != unique.end(); ++uIter) {
174 for(
int d = 0; d < 3; d++) {
175 data(d, idx) = pp[d];
176 vmins(d) = std::min(vmins(d), pp[d]);
177 vmaxs(d) = std::max(vmaxs(d), pp[d]);
183 for(
int i = 0; i < 3; i++) { mean(i) /= num_vertices; }
187 for(
int i = 0; i < 3; i++) {
188 for(
int j = 0; j < num_vertices; j++) { B(i, j) = data(i, j) - mean(i); }
194 covariance.
scale(1. / (num_vertices - 1));
201 for(
int i = 0; i < 3; i++) {
202 for(
int j = 0; j < 3; j++) {
203 if(std::abs(covariance(i, j)) < 10e-16) covariance(i, j) = 0;
211 covariance.
eig(real_eig, img_eig, left_eigv, right_eigv,
true);
219 for(
int i = 0; i < 3; i++) {
222 for(
int j = 0; j < num_vertices; j++) {
223 maxs(i) = std::max(maxs(i), projected(i, j));
224 mins(i) = std::min(mins(i), projected(i, j));
232 for(
int i = 0; i < 3; i++) {
233 sizes[i] = maxs(i) - mins(i);
237 if(sizes[0] == 0 && sizes[1] == 0) {
244 Axis1[0] = left_eigv(0, 0);
245 Axis1[1] = left_eigv(1, 0);
246 Axis1[2] = left_eigv(2, 0);
247 Axis2[0] = left_eigv(0, 1);
248 Axis2[1] = left_eigv(1, 1);
249 Axis2[2] = left_eigv(2, 1);
250 Axis3[0] = left_eigv(0, 2);
251 Axis3[1] = left_eigv(1, 2);
252 Axis3[2] = left_eigv(2, 2);
254 center[0] = (vmaxs(0) + vmins(0)) / 2.0;
255 center[1] = (vmaxs(1) + vmins(1)) / 2.0;
256 center[2] = (vmaxs(2) + vmins(2)) / 2.0;
265 int smallest_comp = 0;
266 if(sizes[0] <= sizes[1] && sizes[0] <= sizes[2])
268 else if(sizes[1] <= sizes[0] && sizes[1] <= sizes[2])
270 else if(sizes[2] <= sizes[0] && sizes[2] <= sizes[1])
275 std::vector<SPoint2 *> points;
276 for(
int i = 0; i < num_vertices; i++) {
277 SPoint2 *p =
new SPoint2(projected(smallest_comp == 0 ? 1 : 0, i),
278 projected(smallest_comp == 2 ? 1 : 2, i));
280 for(
auto point = points.begin(); point != points.end(); point++) {
281 if(std::abs((*p)[0] - (**point)[0]) < 10e-10 &&
282 std::abs((*p)[1] - (**point)[1]) < 10e-10) {
287 if(keep) { points.push_back(p); }
296 srand((
unsigned)time(
nullptr));
297 for(std::size_t i = 0; i < points.size(); i++) {
299 points[i]->x() + (10e-6) * sizes[smallest_comp == 0 ? 1 : 0] *
300 (-0.5 + ((
double)rand()) / RAND_MAX);
302 points[i]->y() + (10e-6) * sizes[smallest_comp == 2 ? 1 : 0] *
303 (-0.5 + ((
double)rand()) / RAND_MAX);
309 }
catch(std::runtime_error &e) {
313 std::vector<Segment> convex_hull;
323 for(
int j = 0; j < 3; j++) {
325 for(
auto seg = convex_hull.begin(); seg != convex_hull.end(); seg++) {
326 if(((*seg).from == segs[j].
from && (*seg).from == segs[j].
to)
330 convex_hull.erase(seg);
335 if(okay) { convex_hull.push_back(segs[j]); }
349 least_rectangle.
center[0] = 0.0;
350 least_rectangle.
center[1] = 0.0;
351 least_rectangle.
size[0] = -1.0;
352 least_rectangle.
size[1] = 1.0;
357 for(
auto seg = convex_hull.begin(); seg != convex_hull.end(); seg++) {
361 segment(0) = points[(*seg).from]->x() - points[(*seg).to]->x();
362 segment(1) = points[(*seg).from]->y() - points[(*seg).to]->y();
365 double cosine = axis(0) * segment(0) + segment(1) * axis(1);
366 double sine = axis(1) * segment(0) - segment(1) * axis(0);
369 rotation(0, 0) = cosine;
370 rotation(0, 1) = sine;
371 rotation(1, 0) = -sine;
372 rotation(1, 1) = cosine;
374 auto max_x = -std::numeric_limits<double>::max();
375 auto min_x = std::numeric_limits<double>::max();
376 auto max_y = -std::numeric_limits<double>::max();
377 auto min_y = std::numeric_limits<double>::max();
379 for(
int i = 0; i < record.
numPoints; i++) {
383 pnt(0) = points[i]->x();
384 pnt(1) = points[i]->y();
387 rotation.
mult(pnt, rot_pnt);
389 if(rot_pnt(0) < min_x) min_x = rot_pnt(0);
390 if(rot_pnt(0) > max_x) max_x = rot_pnt(0);
391 if(rot_pnt(1) < min_y) min_y = rot_pnt(1);
392 if(rot_pnt(1) > max_y) max_y = rot_pnt(1);
398 center_before_rot(0) = (max_x + min_x) / 2.0;
399 center_before_rot(1) = (max_y + min_y) / 2.0;
402 rotation_inv(0, 0) = cosine;
403 rotation_inv(0, 1) = -sine;
404 rotation_inv(1, 0) = sine;
405 rotation_inv(1, 1) = cosine;
407 rotation_inv.
mult(center_before_rot, center_rot);
412 rotation_inv.
mult(axis, axis_rot1);
413 rotation_inv.
mult(axis2, axis_rot2);
415 if((least_rectangle.
area() == -1) ||
416 (max_x - min_x) * (max_y - min_y) < least_rectangle.
area()) {
417 least_rectangle.
size[0] = max_x - min_x;
418 least_rectangle.
size[1] = max_y - min_y;
419 least_rectangle.
center[0] = (max_x + min_x) / 2.0;
420 least_rectangle.
center[1] = (max_y + min_y) / 2.0;
421 least_rectangle.
center[0] = center_rot(0);
422 least_rectangle.
center[1] = center_rot(1);
423 least_rectangle.
axisX[0] = axis_rot1(0);
424 least_rectangle.
axisX[1] = axis_rot1(1);
427 least_rectangle.
axisY[0] = axis_rot2(0);
428 least_rectangle.
axisY[1] = axis_rot2(1);
432 auto min_pca = std::numeric_limits<double>::max();
433 auto max_pca = -std::numeric_limits<double>::max();
434 for(
int i = 0; i < num_vertices; i++) {
435 min_pca = std::min(min_pca, projected(smallest_comp, i));
436 max_pca = std::max(max_pca, projected(smallest_comp, i));
438 double center_pca = (max_pca + min_pca) / 2.0;
439 double size_pca = (max_pca - min_pca);
441 double raw_data[3][5];
442 raw_data[0][0] = size_pca;
443 raw_data[1][0] = least_rectangle.
size[0];
444 raw_data[2][0] = least_rectangle.
size[1];
446 raw_data[0][1] = center_pca;
447 raw_data[1][1] = least_rectangle.
center[0];
448 raw_data[2][1] = least_rectangle.
center[1];
450 for(
int i = 0; i < 3; i++) {
451 raw_data[0][2 + i] = left_eigv(i, smallest_comp);
453 least_rectangle.
axisX[0] * left_eigv(i, smallest_comp == 0 ? 1 : 0) +
454 least_rectangle.
axisX[1] * left_eigv(i, smallest_comp == 2 ? 1 : 2);
456 least_rectangle.
axisY[0] * left_eigv(i, smallest_comp == 0 ? 1 : 0) +
457 least_rectangle.
axisY[1] * left_eigv(i, smallest_comp == 2 ? 1 : 2);
466 if(size_pca > least_rectangle.
size[0]) {
468 if(size_pca > least_rectangle.
size[1]) {
471 if(least_rectangle.
size[0] > least_rectangle.
size[1]) {
490 if(size_pca < least_rectangle.
size[1]) {
493 if(least_rectangle.
size[0] > least_rectangle.
size[1]) {
515 for(
int i = 0; i < 3; i++) {
516 size[i] = raw_data[tri[i]][0];
517 center[i] = raw_data[tri[i]][1];
518 Axis1[i] = raw_data[tri[0]][2 + i];
519 Axis2[i] = raw_data[tri[1]][2 + i];
520 Axis3[i] = raw_data[tri[2]][2 + i];
526 for(
int i = 0; i < 3; i++) {
527 aux1(i) = left_eigv(i, smallest_comp);
528 aux2(i) = left_eigv(i, smallest_comp == 0 ? 1 : 0);
529 aux3(i) = left_eigv(i, smallest_comp == 2 ? 1 : 2);
531 center = aux1 * center_pca + aux2 * least_rectangle.
center[0] +
532 aux3 * least_rectangle.
center[1];
548 Msg::Error(
"SOrientedBoundingBox requires mesh module");
560 double size_term = 0.0;
561 for(
int i = 0; i < 3; i++) {
569 double orientation_term = 0.0;
570 for(
int i = 0; i < 3; i++) {
574 return center_term + size_term + orientation_term;