← Назад к вопросам

Как определить, принадлежит ли точка сфере или кубу по её координатам?

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
  • Расширения: Проверка границ, расстояния, иерархические индексы