Skip to content

Commit 155ed39

Browse files
committed
fix singularity in minimum bounding sphere
1 parent 519ea2c commit 155ed39

File tree

2 files changed

+1772
-9
lines changed

2 files changed

+1772
-9
lines changed

sources/libcore/geometry/minimumBoundingSphere.cpp

+34-9
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include <array>
12
#include <vector>
23

34
#include <cage-core/geometry.h>
@@ -25,6 +26,19 @@ namespace cage
2526
Vec3 a = A - O;
2627
Vec3 b = B - O;
2728
Real denom = 2 * dot(cross(a, b), cross(a, b));
29+
if (abs(denom) < 1e-5)
30+
{
31+
Sphere sph[3] = {
32+
MbSphere(O, A),
33+
MbSphere(O, B),
34+
MbSphere(A, B),
35+
};
36+
Sphere b = sph[0];
37+
for (Sphere s : sph)
38+
if (s.radius > b.radius)
39+
b = s;
40+
return b;
41+
}
2842
Vec3 o = (dot(b, b) * cross(cross(a, b), a) + dot(a, a) * cross(b, cross(a, b))) / denom;
2943
return Sphere(O + o, length(o) + 1e-5);
3044
}
@@ -35,6 +49,20 @@ namespace cage
3549
Vec3 b = B - O;
3650
Vec3 c = C - O;
3751
Real denom = 2 * determinant(Mat3(a[0], a[1], a[2], b[0], b[1], b[2], c[0], c[1], c[2]));
52+
if (abs(denom) < 1e-5)
53+
{
54+
Sphere sph[4] = {
55+
MbSphere(O, A, B),
56+
MbSphere(O, A, C),
57+
MbSphere(O, B, C),
58+
MbSphere(A, B, C),
59+
};
60+
Sphere b = sph[0];
61+
for (Sphere s : sph)
62+
if (s.radius > b.radius)
63+
b = s;
64+
return b;
65+
}
3866
Vec3 o = (dot(c, c) * cross(a, b) + dot(b, b) * cross(c, a) + dot(a, a) * cross(b, c)) / denom;
3967
return Sphere(O + o, length(o) + 1e-5);
4068
}
@@ -59,18 +87,15 @@ namespace cage
5987
MB = MbSphere(*P[-1], *P[-2], *P[-3]);
6088
break;
6189
case 4:
62-
return MbSphere(*P[-1], *P[-2], *P[-3], *P[-4]);
90+
MB = MbSphere(*P[-1], *P[-2], *P[-3], *P[-4]);
91+
return MB;
6392
}
6493
for (uint32 i = 0; i < p; i++)
6594
{
6695
if (d2(MB, *P[i]) > 0)
6796
{
6897
for (uint32 j = i; j > 0; j--)
69-
{
70-
const Vec3 *T = P[j];
71-
P[j] = P[j - 1];
72-
P[j - 1] = T;
73-
}
98+
std::swap(P[j], P[j - 1]);
7499
MB = recurseMini(P + 1, i, b + 1);
75100
}
76101
}
@@ -81,19 +106,19 @@ namespace cage
81106
Sphere::Sphere(const Frustum &other)
82107
{
83108
const Frustum::Corners corners = other.corners();
84-
const Vec3 *L[8];
109+
std::array<const Vec3 *, 8> L;
85110
int i = 0;
86111
for (const Vec3 &v : corners.data)
87112
L[i++] = &v;
88-
*this = recurseMini(L, 8, 0);
113+
*this = recurseMini(L.data(), 8, 0);
89114
}
90115

91116
Sphere makeSphere(PointerRange<const Vec3> points)
92117
{
93118
switch (points.size())
94119
{
95120
case 0:
96-
return Sphere();
121+
return Sphere(Vec3(), 0);
97122
case 1:
98123
return Sphere(points[0], 0);
99124
case 2:

0 commit comments

Comments
 (0)