Skip to content

Commit a33a706

Browse files
committed
refactor: reduced overlap logic
1 parent 191658d commit a33a706

2 files changed

Lines changed: 109 additions & 53 deletions

File tree

src/FixedMathSharp/Bounds/BoundingArea.cs

Lines changed: 82 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -193,39 +193,12 @@ public bool Contains(Vector3d point)
193193
/// </remarks>
194194
public bool Intersects(IBound other)
195195
{
196-
switch (other)
196+
return other switch
197197
{
198-
case BoundingBox or BoundingArea:
199-
{
200-
if (Contains(other.Min) && Contains(other.Max))
201-
return true; // Full containment
202-
203-
// Determine which axis is "flat" (thickness zero)
204-
bool flatX = Min.x == Max.x && other.Min.x == other.Max.x;
205-
bool flatY = Min.y == Max.y && other.Min.y == other.Max.y;
206-
bool flatZ = Min.z == Max.z && other.Min.z == other.Max.z;
207-
208-
if (flatZ) // Rectangle in XY
209-
return !(Max.x < other.Min.x || Min.x > other.Max.x ||
210-
Max.y < other.Min.y || Min.y > other.Max.y);
211-
else if (flatY) // Rectangle in XZ
212-
return !(Max.x < other.Min.x || Min.x > other.Max.x ||
213-
Max.z < other.Min.z || Min.z > other.Max.z);
214-
else if (flatX) // Rectangle in YZ
215-
return !(Max.y < other.Min.y || Min.y > other.Max.y ||
216-
Max.z < other.Min.z || Min.z > other.Max.z);
217-
else // fallback to 3D volume logic
218-
return !(Max.x < other.Min.x || Min.x > other.Max.x ||
219-
Max.y < other.Min.y || Min.y > other.Max.y ||
220-
Max.z < other.Min.z || Min.z > other.Max.z);
221-
}
222-
case BoundingSphere sphere:
223-
// Find the closest point on the area to the sphere's center
224-
// Intersection occurs if the distance from the closest point to the sphere’s center is within the radius.
225-
return Vector3d.SqrDistance(sphere.Center, this.ProjectPointWithinBounds(sphere.Center)) <= sphere.SqrRadius;
226-
227-
default: return false; // Default case for unknown or unsupported types
228-
}
198+
BoundingBox or BoundingArea => IntersectsBoxLike(other.Min, other.Max),
199+
BoundingSphere sphere => IntersectsSphere(sphere),
200+
_ => false
201+
};
229202
}
230203

231204
/// <summary>
@@ -237,6 +210,82 @@ public Vector3d ProjectPoint(Vector3d point)
237210
return this.ProjectPointWithinBounds(point);
238211
}
239212

213+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
214+
private bool IntersectsBoxLike(Vector3d otherMin, Vector3d otherMax)
215+
{
216+
Vector3d min = Min;
217+
Vector3d max = Max;
218+
219+
if (ContainsPoint(otherMin, min, max) && ContainsPoint(otherMax, min, max))
220+
return true;
221+
222+
if (IsFlatAlongZ(min, max, otherMin, otherMax))
223+
return OverlapsOnXY(min, max, otherMin, otherMax);
224+
225+
if (IsFlatAlongY(min, max, otherMin, otherMax))
226+
return OverlapsOnXZ(min, max, otherMin, otherMax);
227+
228+
if (IsFlatAlongX(min, max, otherMin, otherMax))
229+
return OverlapsOnYZ(min, max, otherMin, otherMax);
230+
231+
return OverlapsOnAllAxes(min, max, otherMin, otherMax);
232+
}
233+
234+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
235+
private bool IntersectsSphere(BoundingSphere sphere)
236+
{
237+
return Vector3d.SqrDistance(sphere.Center, this.ProjectPointWithinBounds(sphere.Center)) <= sphere.SqrRadius;
238+
}
239+
240+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
241+
private static bool ContainsPoint(Vector3d point, Vector3d min, Vector3d max)
242+
{
243+
return point.x >= min.x && point.x <= max.x
244+
&& point.y >= min.y && point.y <= max.y
245+
&& point.z >= min.z && point.z <= max.z;
246+
}
247+
248+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
249+
private static bool IsFlatAlongX(Vector3d min, Vector3d max, Vector3d otherMin, Vector3d otherMax)
250+
=> min.x == max.x && otherMin.x == otherMax.x;
251+
252+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
253+
private static bool IsFlatAlongY(Vector3d min, Vector3d max, Vector3d otherMin, Vector3d otherMax)
254+
=> min.y == max.y && otherMin.y == otherMax.y;
255+
256+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
257+
private static bool IsFlatAlongZ(Vector3d min, Vector3d max, Vector3d otherMin, Vector3d otherMax)
258+
=> min.z == max.z && otherMin.z == otherMax.z;
259+
260+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
261+
private static bool OverlapsOnXY(Vector3d min, Vector3d max, Vector3d otherMin, Vector3d otherMax)
262+
{
263+
return !(max.x < otherMin.x || min.x > otherMax.x ||
264+
max.y < otherMin.y || min.y > otherMax.y);
265+
}
266+
267+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
268+
private static bool OverlapsOnXZ(Vector3d min, Vector3d max, Vector3d otherMin, Vector3d otherMax)
269+
{
270+
return !(max.x < otherMin.x || min.x > otherMax.x ||
271+
max.z < otherMin.z || min.z > otherMax.z);
272+
}
273+
274+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
275+
private static bool OverlapsOnYZ(Vector3d min, Vector3d max, Vector3d otherMin, Vector3d otherMax)
276+
{
277+
return !(max.y < otherMin.y || min.y > otherMax.y ||
278+
max.z < otherMin.z || min.z > otherMax.z);
279+
}
280+
281+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
282+
private static bool OverlapsOnAllAxes(Vector3d min, Vector3d max, Vector3d otherMin, Vector3d otherMax)
283+
{
284+
return !(max.x < otherMin.x || min.x > otherMax.x ||
285+
max.y < otherMin.y || min.y > otherMax.y ||
286+
max.z < otherMin.z || min.z > otherMax.z);
287+
}
288+
240289
#endregion
241290

242291
#region Operators
@@ -270,4 +319,4 @@ public override int GetHashCode()
270319
}
271320

272321
#endregion
273-
}
322+
}

src/FixedMathSharp/Bounds/BoundingBox.cs

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -246,26 +246,12 @@ public bool Contains(Vector3d point)
246246
/// </remarks>
247247
public bool Intersects(IBound other)
248248
{
249-
switch (other)
249+
return other switch
250250
{
251-
case BoundingBox or BoundingArea:
252-
{
253-
if (Contains(other.Min) && Contains(other.Max))
254-
return true; // Full containment
255-
256-
// General intersection logic (allowing for overlap)
257-
return !(Max.x <= other.Min.x || Min.x >= other.Max.x ||
258-
Max.y <= other.Min.y || Min.y >= other.Max.y ||
259-
Max.z <= other.Min.z || Min.z >= other.Max.z);
260-
}
261-
case BoundingSphere sphere:
262-
// project the sphere’s center onto the 3D volume and checks the distance to the surface.
263-
// If the distance from the closest point to the center is less than or equal to the sphere’s radius, they intersect.
264-
return Vector3d.SqrDistance(sphere.Center, this.ProjectPointWithinBounds(sphere.Center)) <= sphere.SqrRadius;
265-
266-
default:
267-
return false; // Default case for unknown or unsupported types
268-
}
251+
BoundingBox or BoundingArea => IntersectsBoxLike(other.Min, other.Max),
252+
BoundingSphere sphere => IntersectsSphere(sphere),
253+
_ => false
254+
};
269255
}
270256

271257
/// <summary>
@@ -275,6 +261,27 @@ public bool Intersects(IBound other)
275261
public Vector3d ProjectPoint(Vector3d point)
276262
=> this.ProjectPointWithinBounds(point);
277263

264+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
265+
private bool IntersectsBoxLike(Vector3d otherMin, Vector3d otherMax)
266+
{
267+
return Contains(otherMin) && Contains(otherMax)
268+
|| HasStrictAxisOverlap(otherMin, otherMax);
269+
}
270+
271+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
272+
private bool IntersectsSphere(BoundingSphere sphere)
273+
{
274+
return Vector3d.SqrDistance(sphere.Center, this.ProjectPointWithinBounds(sphere.Center)) <= sphere.SqrRadius;
275+
}
276+
277+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
278+
private bool HasStrictAxisOverlap(Vector3d otherMin, Vector3d otherMax)
279+
{
280+
return !(Max.x <= otherMin.x || Min.x >= otherMax.x ||
281+
Max.y <= otherMin.y || Min.y >= otherMax.y ||
282+
Max.z <= otherMin.z || Min.z >= otherMax.z);
283+
}
284+
278285
/// <summary>
279286
/// Calculates the shortest distance from a given point to the surface of the bounding box.
280287
/// If the point lies inside the box, the distance is zero.
@@ -468,4 +475,4 @@ public override int GetHashCode()
468475
}
469476

470477
#endregion
471-
}
478+
}

0 commit comments

Comments
 (0)