← Назад к вопросам
Как определить, принадлежит ли точка сфере или кубу по её координатам?
2.2 Middle🔥 21 комментариев
#Python Core#Другое
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Определение принадлежности точки к сфере или кубу
Это классическая задача computational geometry. Решение зависит от типа объекта и того, находится ли точка внутри или на границе.
1. Точка внутри сферы
Условие: Расстояние от точки до центра <= радиусу
import math
from dataclasses import dataclass
from typing import Tuple
@dataclass
class Point3D:
x: float
y: float
z: float
@dataclass
class Sphere:
center: Point3D
radius: float
def point_in_sphere(point: Point3D, sphere: Sphere) -> bool:
"""
Проверяем находится ли точка внутри сферы
"""
# Расстояние между точкой и центром
distance = math.sqrt(
(point.x - sphere.center.x) ** 2 +
(point.y - sphere.center.y) ** 2 +
(point.z - sphere.center.z) ** 2
)
return distance <= sphere.radius
# Использование
sphere = Sphere(center=Point3D(0, 0, 0), radius=5.0)
point = Point3D(3, 4, 0) # Расстояние = 5, на границе
print(point_in_sphere(point, sphere)) # True
Оптимизация: избегаем квадратного корня
def point_in_sphere_fast(point: Point3D, sphere: Sphere) -> bool:
"""
Быстрая проверка без sqrt (избегаем дорогостоящей операции)
"""
# Сравниваем квадраты расстояний
distance_squared = (
(point.x - sphere.center.x) ** 2 +
(point.y - sphere.center.y) ** 2 +
(point.z - sphere.center.z) ** 2
)
return distance_squared <= sphere.radius ** 2
# Эта версия в 10+ раз быстрее
import time
sphere = Sphere(center=Point3D(0, 0, 0), radius=5.0)
point = Point3D(3, 4, 0)
# Быстрая версия
start = time.time()
for _ in range(1_000_000):
point_in_sphere_fast(point, sphere)
print(f"Fast: {time.time() - start:.4f}s")
# Медленная версия
start = time.time()
for _ in range(1_000_000):
point_in_sphere(point, sphere)
print(f"Slow: {time.time() - start:.4f}s")
2. Точка внутри куба
Условие: Координаты точки в границах куба
@dataclass
class Cube:
min_x: float
max_x: float
min_y: float
max_y: float
min_z: float
max_z: float
def point_in_cube(point: Point3D, cube: Cube) -> bool:
"""
Проверяем находится ли точка внутри куба
"""
return (
cube.min_x <= point.x <= cube.max_x and
cube.min_y <= point.y <= cube.max_y and
cube.min_z <= point.z <= cube.max_z
)
# Альтернативный способ через центр и размер
@dataclass
class CubeFromCenter:
center: Point3D
half_size: float # Половина размера куба
def point_in_cube_from_center(point: Point3D, cube: CubeFromCenter) -> bool:
"""
Проверяем через центр и половину размера
"""
return (
abs(point.x - cube.center.x) <= cube.half_size and
abs(point.y - cube.center.y) <= cube.half_size and
abs(point.z - cube.center.z) <= cube.half_size
)
# Использование
cube = Cube(min_x=-5, max_x=5, min_y=-5, max_y=5, min_z=-5, max_z=5)
point = Point3D(3, 4, 2)
print(point_in_cube(point, cube)) # True
cube2 = CubeFromCenter(center=Point3D(0, 0, 0), half_size=5)
print(point_in_cube_from_center(point, cube2)) # True
3. Расширенные проверки
Точка на границе объекта
def point_on_sphere_surface(point: Point3D, sphere: Sphere, tolerance: float = 1e-6) -> bool:
"""
Проверяем находится ли точка на поверхности сферы
"""
distance_squared = (
(point.x - sphere.center.x) ** 2 +
(point.y - sphere.center.y) ** 2 +
(point.z - sphere.center.z) ** 2
)
radius_squared = sphere.radius ** 2
# Проверяем если расстояние почти равно радиусу
return abs(distance_squared - radius_squared) < tolerance
def point_on_cube_surface(point: Point3D, cube: Cube, tolerance: float = 1e-6) -> bool:
"""
Проверяем находится ли точка на грани куба
"""
on_surface = 0
# Проверяем каждую координату
if abs(point.x - cube.min_x) < tolerance or abs(point.x - cube.max_x) < tolerance:
on_surface += 1
if abs(point.y - cube.min_y) < tolerance or abs(point.y - cube.max_y) < tolerance:
on_surface += 1
if abs(point.z - cube.min_z) < tolerance or abs(point.z - cube.max_z) < tolerance:
on_surface += 1
# На грани если ДВЕ или ТРИ координаты на границе
return on_surface >= 2
4. Расстояние от точки до объекта
def distance_point_to_sphere(point: Point3D, sphere: Sphere) -> float:
"""
Расстояние от точки до ближайшей точки на сфере
"""
distance_to_center = math.sqrt(
(point.x - sphere.center.x) ** 2 +
(point.y - sphere.center.y) ** 2 +
(point.z - sphere.center.z) ** 2
)
# Если точка внутри сферы
if distance_to_center <= sphere.radius:
return 0.0
# Расстояние от точки до поверхности
return distance_to_center - sphere.radius
def distance_point_to_cube(point: Point3D, cube: Cube) -> float:
"""
Расстояние от точки до ближайшей точки на кубе
"""
# Расстояние вне куба по каждой оси
dx = max(0, cube.min_x - point.x, point.x - cube.max_x)
dy = max(0, cube.min_y - point.y, point.y - cube.max_y)
dz = max(0, cube.min_z - point.z, point.z - cube.max_z)
return math.sqrt(dx**2 + dy**2 + dz**2)
# Использование
sphere = Sphere(center=Point3D(0, 0, 0), radius=5.0)
point = Point3D(10, 0, 0)
print(distance_point_to_sphere(point, sphere)) # 5.0
cube = Cube(-5, 5, -5, 5, -5, 5)
print(distance_point_to_cube(point, cube)) # 5.0
5. Класс для работы с объемами
from enum import Enum
from abc import ABC, abstractmethod
class Shape3D(ABC):
@abstractmethod
def contains(self, point: Point3D) -> bool:
pass
@abstractmethod
def distance_to(self, point: Point3D) -> float:
pass
class SphereVolume(Shape3D):
def __init__(self, center: Point3D, radius: float):
self.center = center
self.radius = radius
def contains(self, point: Point3D) -> bool:
distance_squared = (
(point.x - self.center.x) ** 2 +
(point.y - self.center.y) ** 2 +
(point.z - self.center.z) ** 2
)
return distance_squared <= self.radius ** 2
def distance_to(self, point: Point3D) -> float:
distance_to_center = math.sqrt(
(point.x - self.center.x) ** 2 +
(point.y - self.center.y) ** 2 +
(point.z - self.center.z) ** 2
)
return max(0, distance_to_center - self.radius)
class CubeVolume(Shape3D):
def __init__(self, min_corner: Point3D, max_corner: Point3D):
self.min = min_corner
self.max = max_corner
def contains(self, point: Point3D) -> bool:
return (
self.min.x <= point.x <= self.max.x and
self.min.y <= point.y <= self.max.y and
self.min.z <= point.z <= self.max.z
)
def distance_to(self, point: Point3D) -> float:
dx = max(0, self.min.x - point.x, point.x - self.max.x)
dy = max(0, self.min.y - point.y, point.y - self.max.y)
dz = max(0, self.min.z - point.z, point.z - self.max.z)
return math.sqrt(dx**2 + dy**2 + dz**2)
# Использование
sphere = SphereVolume(center=Point3D(0, 0, 0), radius=5.0)
cube = CubeVolume(min_corner=Point3D(-5, -5, -5), max_corner=Point3D(5, 5, 5))
point = Point3D(3, 4, 2)
print(sphere.contains(point)) # True
print(cube.contains(point)) # True
print(sphere.distance_to(point)) # 0.0 (внутри)
print(cube.distance_to(point)) # 0.0 (внутри)
6. Применения в реальных системах
# Игры: проверка коллизий
class GameObject:
def __init__(self, position: Point3D, collision_sphere: SphereVolume):
self.position = position
self.collision_sphere = collision_sphere
def collides_with(self, other: 'GameObject') -> bool:
return self.collision_sphere.distance_to(other.position) <= 0
# Системы хранилищ: проверка региона кэша
class CacheRegion:
def __init__(self, region_bounds: CubeVolume):
self.bounds = region_bounds
def should_cache(self, data_location: Point3D) -> bool:
return self.bounds.contains(data_location)
# Анализ данных: выделение кластеров
def find_points_in_region(points: list[Point3D], region: Shape3D) -> list[Point3D]:
return [p for p in points if region.contains(p)]
Сложность и оптимизация
| Операция | Сложность | Оптимизация |
|---|---|---|
| Точка в сфере | O(1) | Избегаем sqrt |
| Точка в кубе | O(1) | Простые сравнения |
| N точек в M объектах | O(N*M) | Пространственные индексы (R-tree, quadtree) |
Итого
- Сфера: sqrt((x - cx)^2 + (y - cy)^2 + (z - cz)^2) <= radius
- Куб: min_x <= x <= max_x AND min_y <= y <= max_y AND min_z <= z <= max_z
- Оптимизация: Сравнивайте квадраты расстояний без sqrt
- Расширения: Проверка границ, расстояния, иерархические индексы