Книга: Написание скриптов для Blender 2.49

Определение центра масс меша

Определение центра масс меша

При печати трехмерного объекта в пластмассе или металле, возможно, всплывёт невинный на вид вопрос, как только мы создадим нашу первую игрушку, основанную на созданном нами меше; где его центр масс? Если наша модель имеет ноги, и мы не хотим, чтобы она неожиданно упала, лучше бы центр масс находился где-нибудь над её ногами, и, по возможности внизу, чтобы она держалась стабильно. Схематически это показано на картинке:


Как только мы узнали, как определять объем меша, мы можем взять оттуда и по-новой использовать многие концепции для разработки скрипта, определяющего центр масс. Нам необходимо знать два дополнительных момента для вычисления позиции центра масс:

• Центры массы проецированных объемов мы построим при расчете объема меша

• Как складывать рассчитанные центры масс всех этих индивидуальных объемов

Все это допускает, что твердые части нашего меша имеют однородную плотность. Меш может иметь любую форму или даже быть полым, но для твердых частей принимается, что их плотность однородна. Это разумное предположение для материалов, осаждаемых 3D-принтерами.

Первый вопрос заключает в себе немного геометрии: спроецированный объем - по существу треугольная колонна (или треугольная призма), закрытая, возможно, наклонной треугольной гранью. Расчет центра масс можно сделать следующим образом: координаты x и y центра масс являются координатами x и y центра спроецированного треугольника на плоскость xy - это просто среднее арифметическое координат x и y соответственно трех точек задающих треугольную грань. Координата z центра масс - это половина средней высоты нашей спроецированной колонны. Это - среднее арифметическое z-координат трех точек треугольной грани, поделенное на два.

К сожалению, такой простой расчет средних значений координат не даст точного положения центра масс, в отличие от расчета объёма в предыдущем разделе. Этот вопрос заключает в себе не «немного геометрии», а много матана. Точный расчет включает в себя, как минимум, вычисление двойного интеграла по площади спроецированного треугольника (для расчета ЦМ произвольного трёхмерного тела необходим тройной интеграл). Формулы расчета координат ЦМ есть, например, в этой книге: http://www.toroid.ru/zaporojecGI.html, стр. 281, пример расчета для похожей призмы (правда, с квадратным основанием) на стр. 285. Совпадение результатов применяемого автором метода с точным возможно только в случае горизонтальности треугольной грани, в остальных случаях будет присутствовать погрешность. Конечно, если площадь треугольника мала, а высота столба много больше любой из сторон этого треугольника (обычная ситуация в высокополигональном меше), то погрешность будет небольшой, однако она всё равно во много раз больше, чем погрешности, обсуждаемые в следующем разделе.  — наглая отсебятина переводчика.

Второй вопрос заключен главным образом в здравом смысле: даны две массы m1 и m2 с их центрами масс в v1 и v2 соответственно, их комбинированный центр масс является средне взвешенным. То есть, центр масс - пропорционально ближе к центру масс тяжелого компонента. 


Конечно, это у нас теперь здравый смысл, но кто-то вроде Архимеда должен был увидеть, где здесь действительно здравый смысл. После нахождения этого 'закона рычагов' (как он назвал это), он не кричал "эврика!" и не бегал голым, так что потребовалось отчасти больше времени для привлечения внимания.

Давайте поместим всю эту информацию в рецепт, которому мы можем последовать:

1. Убедиться, что у всех граней нормали единообразно указывают наружу.

2. Для всех граней:

• Вычислить z-компоненту вектора нормали грани Nz

• Вычислить произведение P среднего числа z-координат и площади спроецированной поверхности.

• Вычислить ЦМ(x, y, z) с x, y, как среднее от спроецированных координат x, y,  и z как (среднее число z-координат грани)/2

• Если Nz положителен: прибавить P, умноженное на  ЦМ

• Если Nz отрицателен: отнять P, умноженное на  ЦМ

Из схемы выше ясно, что расчет центра масс идет рука об руку с вычислением частичных объемов, так что имеет смысл переопределить функцию meshvolume() в следующую:

def meshvolume(me):
   volume = 0.0
   cm = vec((0,0,0))
   for f in me.faces:
      xy_area = Mathutils.TriangleArea(vec(f.v[0].co[:2]),
                vec(f.v[1].co[:2]),vec(f.v[2].co[:2]))
      Nz = f.no[2]
      avg_z = sum([f.v[i].co[2] for i in range(3)])/3.0
      partial_volume = avg_z * xy_area
      if Nz < 0: volume -= partial_volume
      if Nz > 0: volume += partial_volume
      avg_x = sum([f.v[i].co[0] for i in range(3)])/3.0
      avg_y = sum([f.v[i].co[1] for i in range(3)])/3.0
      centroid = vec((avg_x,avg_y,avg_z/2))
      if Nz < 0: cm -= partial_volume * centroid
      if Nz > 0: cm += partial_volume * centroid
   return volume,cm/volume

Добавленные или изменённые строки выделены

Оглавление книги


Генерация: 1.339. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз