#python #physics
#python #физика
Вопрос:
Я полный новичок в обоих симуляциях, поэтому этот вопрос может показаться глупым. Если да, пожалуйста, не стесняйтесь редактировать его. Я пытаюсь смоделировать следующий сценарий на Python. Я случайным образом помещаю несколько маленьких частиц в 2D-поле с фиксированными размерами. Каждая частица имеет радиус воздействия r
. Если первая частица имеет вторую в радиусе своего действия, то к обеим частицам должна быть применена сила (эффект, который первая оказывает на вторую, и наоборот), и моя функция силы определяется как:
f(i,j)_n = (r - |pi_n - pj_n|)((pj_n - pi_n)/|pi_n - pj_n|)
где n
— текущий временной шаг, pi_n
представляет положение i
на временном шаге n
и ||
представляет вычисление величины и (pj_n - pi_n)
представляет вычитание вектора.
Мне было интересно, есть ли какие-либо библиотеки, которые упрощают этот материал для меня. Все, что мне нужно, это в основном следующее:
time-step particle position(x,y)
У кого-нибудь есть какие-нибудь предложения для меня, пожалуйста?
Комментарии:
1. Если вы абсолютный новичок в симуляциях, я бы рекомендовал попробовать написать это самостоятельно. Эти библиотеки могут немного сбить с толку новичков. Кроме того, вы сможете изучить материал.
Ответ №1:
Поиск в Google для python library vector 2d
возвращенных http://www.supereffective.org/pages/Vector-2d-Vector-Library в качестве главного хита, который кажется компетентной библиотекой (содержащей проекцию и перпендикуляризацию, нормализацию, вращение, масштабирование и т.д.)
Пока количество частиц не слишком велико, это должно отлично работать в сочетании со схемой интеграции. например, вы отслеживаете векторы каждой частицы (pos, vel) и, возможно, также ускорения и используете:
F = m a
-> F = m dv/dt
-> dv/dt = F/m
и таким образом
dv ~= dt*F/m
-> v' - v ~= dt*F/m
-> ball.vel = timeStep*sum(ball.force(n) for n in ball.neighbors())/ball.mass
Это интеграция Эйлера, которая обладает довольно плохими свойствами, но подходит для игры.
Ответ №2:
Мне действительно нравится библиотека физики pymunk, оболочка для библиотеки физики бурундука.
Прежде всего, необходимо инициализировать библиотеку:
import pymunk
pymunk.init_pymunk()
space = pymunk.Space()
space.gravity = (0.0, -100.0)
Чтобы достичь чего-то подобного, что вы просили, вам нужно создать Body
и Circle
форму для каждой частицы, которую вы хотите создать.
mass = 1
radius = 14
inertia = pymunk.moment_for_circle(mass, 0, radius, (0,0))
body = pymunk.Body(mass, inertia)
x, y = random.randint(0, 200), random.randint(0, 200)
body.position = x, 550
shape = pymunk.Circle(body, radius, (0,0))
shape.sensor = True
space.add(body, shape)
Частицы не будут сталкиваться друг с другом, потому что sensor
флаг установлен на True
. Радиус теперь является чем-то вроде области влияния.
Теперь мы создаем функцию обратного вызова для частиц, которые имеют перекрывающуюся область влияния:
def near_callback(space, arbiter, *args, **kwargs):
body_i = arbiter.shapes[0].body
body_j = arbiter.shapes[1].body
# calculate the forces force_i and force_j with your formula
...
body_i.apply_force(force_i)
body_j.apply_force(force_j)
Обратный вызов задается в space
:
space.set_default_collision_handler(near_callback, near_callback, None, None, None)
Конечно, space
должно быть «пошаговым» для каждого временного интервала:
space.step(dt)
Я надеюсь, что это было несколько понятно и полезно.
Комментарии:
1. Я знаю, что это довольно поздно, но я возвращаюсь к этому вопросу и проверяю ваш ответ. Не могли бы вы указать мне на какой-либо полезный материал, связанный с pymunk? Я устанавливал
dt=1
и выполнялspace.step(dt)
почти 100 раз, но обратный вызов так и не был вызван. Может быть, я делаю что-то тривиально неправильное. Не могли бы вы показать рабочий пример, с которым я могу поиграть?