Программирование топологических данных

From FreeCAD Documentation
Revision as of 15:40, 2 February 2011 by Psi13art (talk | contribs)

Введение

Здесь мы объясним вам как управлять Модулем Деталей напрямую из интепритатора python FreeCAD, или из любого внешнего сценария. Для уверенности , просмотрите раздел Написание Сценариев и страницу Основ сценариев в FreeCAD если вам необходимо больше информации, о том как работает написание сценариев в FreeCAD.

Для первого использования функциональности модуля Деталей вы должны загрузить модуль Деталей в интепретатор: import Part

Диаграмма Классов

Это UML обзор наиболее важных классов модуля Деталей:

Python классы содержащиеся в модуле Деталей
Python классы содержащиеся в модуле Деталей

Геометрия

Геометрические объекты являются строительными блоками для всех топологических объектов:

  • GEOM Базовый класс геометрических объектов
  • LINE Прямая линия в 3D, задается начальной и конечной точкой
  • CIRCLE Окружность или дуга задается центром, начальной и конечной точкой
  • ...... И вскоре еще немного ;-)

Топология

Доступны нижеследующие топологические типы данных:

  • COMPOUND Группа из топологических объектов любого типа.
  • COMPSOLID Составное твердое тело, как набор твердых тел соединенными гранями. Он расширяет понятие Ломаной кривой(WIRE) и оболочки(SHELL) для твердых тел.
  • SOLID Часть пространства ограниченная оболочкой. Она трехмерная.
  • SHELL Набор граней соединенных между собой через ребра. Оболочки могут быть открытыми или закрытыми.
  • FACE В 2D это часть плоскости; в 3D это часть поверхности. Это геометрия ограничена (обрезана) по контуам. Она двухмерная.
  • WIRE Набор ребер соединенных через вершины. Он может быть как открытым, так и закрытым в зависимости от того связаны ли крайние ребра или нет.
  • EDGE Топологический элемент соответствующий ограниченной кривой. Ребро как правило ограничивается вершинами. Оно одномерное.
  • VERTEX Топологический элемент соответствующий точке. Обладает нулевой размерность.
  • SHAPE общий термин охватывающий все выше сказанное.

Создание базовых типов

Краткое описание

Вы легко можете создать базовый топологический объект с помощью методов "make...()" содержащихся в модуле Деталей:

b = Part.makeBox(100,100,100)
Part.show(b)

Куча других доступных make...() методов:

  • makeBox(l,w,h,[p,d]) -- Создает коробку расположенную в точке p и в указанном направлении d с размерами (l,w,h). По умолчанию p установлен как Vector(0,0,0) и d установлен как Vector(0,0,1)
  • makeCircle(radius,[p,d,angle1,angle2]) -- Создает окружность с заданным радиусом. По умолчанию p=Vector(0,0,0), d=Vector(0,0,1), angle1=0 и angle2=360
  • makeCompound(list) -- Создает составное тело из списка форм
  • makeCone(radius1,radius2,height,[p,d,angle]) -- Создает конус с заданным радиусами и высотой. По умолчанию p=Vector(0,0,0), d=Vector(0,0,1) и angle=360
  • makeCylinder(radius,height,[p,d,angle]) -- Создает цилиндр с заданным радиусом и высотой. По умолчанию p=Vector(0,0,0), d=Vector(0,0,1) и angle=360
  • makeLine((x1,y1,z1),(x2,y2,z2)) -- Создает линию проходящую через две точки
  • makePlane(length,width,[p,d]) -- Создает плоскость с заданной длинной и шириной. По умолчанию p=Vector(0,0,0) и d=Vector(0,0,1)
  • makePolygon(list) -- Создает многоугольник из списка точек
  • makeSphere(radius,[p,d,angle1,angle2,angle3]) -- Создает сферу с заданным радиусом. По умолчанию p=Vector(0,0,0), d=Vector(0,0,1), angle1=0, angle2=90 и angle3=360
  • makeTorus(radius1,radius2,[p,d,angle1,angle2,angle3]) -- Создает тор по заданными радиусамi.По умолчанию p=Vector(0,0,0), d=Vector(0,0,1), angle1=0, angle2=360 и angle3=360

Подробные объяснения

Сначала импортируем следующее:

>>> import Part
>>> from FreeCAD import Base


Как создать Вершину?


>>> vertex = Part.Vertex((1,0,0))

Вершина это точка созданная в x=1,y=0,z=0 устанавливающая(задающая) объект вершины,вот так, вы можете найти её расположение:


>>> vertex.Point
Vector (1, 0, 0)

Как создать Ребро?

Ребра не что иное как линия с двумя вершинами:


>>> edge = Part.makeLine((0,0,0), (10,0,0))
>>> edge.Vertexes
[<Vertex object at 01877430>, <Vertex object at 014888E0>]

Примечание: Вы не можете создать ребро передав две вершины. Вы можете узнать длинну и центр ребра, вот так:


>>> edge.Length
10.0
>>> edge.CenterOfMass
Vector (5, 0, 0)

Как создать ломанную кривую?

Ломанная может быть создана из списка ребер или даже из списка ломаных:


>>> edge1 = Part.makeLine((0,0,0), (10,0,0))
>>> edge2 = Part.makeLine((10,0,0), (10,10,0))
>>> wire1 = Part.Wire([edge1,edge2]) 
>>> edge3 = Part.makeLine((10,10,0), (0,10,0))
>>> edge4 = Part.makeLine((0,10,0), (0,0,0))
>>> wire2 = Part.Wire([edge3,edge4])
>>> wire3 = Part.Wire([wire1,wire2])
>>> wire3.Edges
[<Edge object at 016695F8>, <Edge object at 0197AED8>, <Edge object at 01828B20>, 
 <Edge object at 0190A788>]
>>> Part.show(wire3)

Part.show(wire3) будет отображать четыре лини как квадарат:


>>> wire3.Length
40.0
>>> wire3.CenterOfMass
Vector (5, 5, 0)
>>> wire3.isClosed()
True
>>> wire2.isClosed()
False

Как создать Грань?

Действительны , только грани созданные из замкнутых ломаных. В данном примере, wire3 замкнутая ломанная,а wire2 не замкнута (смотри выше)


>>> face = Part.Face(wire3)
>>> face.Area
99.999999999999972
>>> face.CenterOfMass
Vector (5, 5, 0)
>>> face.Length
40.0
>>> face.isValid()
True
>>> sface = Part.Face(wire2)
>>> face.isValid()
False

Только грани обладают поверхностью, а не ломанные и ребра.

Как создать окружность?

circle = Part.makeCircle(radius,[center,dir_normal,angle1,angle2]) -- Создает окружность с заданным радиусом

По умолчанию, center=Vector(0,0,0), dir_normal=Vector(0,0,1), angle1=0 and angle2=360. Окружность может быть просто создана, как здесь:


>>> circle = Part.makeCircle(10)
>>> circle.Curve
Circle (Radius : 10, Position : (0, 0, 0), Direction : (0, 0, 1))

Если вы хотите создать её с определенным положением и в определенном направлении


>>> ccircle = Part.makeCircle(10, Base.Vector(10,0,0), Base.Vector(1,0,0))
>>> ccircle.Curve
Circle (Radius : 10, Position : (10, 0, 0), Direction : (1, 0, 0))

Окружность будет создана на расстоянии 10 от базовой(оригинальной) координаты х x и будет обращена в сторону оси x. Примечание: makeCircleпринимает только тип Base.Vector() в качестве позиции и нормали а не кортеж. Вы также можете создать часть окружности, задав угол начальный и конечный угол, как тут:


>>> from math import pi
>>> arc1 = Part.makeCircle(10, Base.Vector(0,0,0), Base.Vector(0,0,1), 0, 180)
>>> arc2 = Part.makeCircle(10, Base.Vector(0,0,0), Base.Vector(0,0,1), 180, 360)

Обе arc1 и arc2 вместе составляют окружность. Углы задаются в градусах, если вы хотите задать раддианами, просто преобразуйте используя формулу: degrees = radians * 180/PI или используя pythonовский math модуль (прежде, конечно, выполнив import math): degrees = math.degrees(radians)

Как создать Дугу по точкам?

К сожалению нет функции makeArc но мы обладаем функцией Part.Arc для созданимя дуги проходящей через три точки. В основном эта может быть дуга соединящая начальную и конечную точку через средню точку. Part.Arc создает объект дугу on which на котором .toShape() вызванная для получения объекта ребра, которое обычно создается с помошью makeLine или makeCircle


>>> arc = Part.Arc(Base.Vector(0,0,0),Base.Vector(0,5,0),Base.Vector(5,5,0))
>>> arc
<Arc object>
>>> arc_edge = arc.toShape()

Примечание: Дуга допускает только Base.Vector() для задания точек, а не кортеж. arc_edge это то что мы хотим, мы можем показать его используя Part.show(arc_edge). Если вы хотите небольшую часть круга, в качестве дуги, это тоже возможно:


>>> from math import pi
>>> circle = Part.Circle(Base.Vector(0,0,0),Base.Vector(0,0,1),10)
>>> arc = Part.Arc(circle,0,pi)

Как создать многоугольник или линию по точкам?

Линия по нескольким точкам, не что иное как создание ломаной с множеством ребер. функция makePolygon берет список точек и создает ломанную по этим точкам:


>>> lshape_wire = Part.makePolygon([Base.Vector(0,5,0),Base.Vector(0,0,0),Base.Vector(5,0,0)])

Как создать плоскость?

Плоскасть это ровная поверхность, в смысле 2D грань makePlane(length,width,[start_pnt,dir_normal]) -- Создает плоскость По умолчанию start_pnt=Vector(0,0,0) и dir_normal=Vector(0,0,1). dir_normal=Vector(0,0,1) создат плоскость нормальную к оси z. dir_normal=Vector(1,0,0) создат плоскость нормальную к оси х:


>>> plane = Part.makePlane(2,2)
>>> plane
<Face object at 028AF990>
>>> plane = Part.makePlane(2,2, Base.Vector(3,0,0), Base.Vector(0,1,0))
>>> plane.BoundBox
BoundBox (3, 0, 0, 5, 0, 2)

BoundBox является параллелепипед вмещающих плоскость с диагональю, начиная с (3,0,0) и концом в (5,0,2). Здесь толщинаhe BoundBoxпо оси y равна нулю. примечание: makePlane доступны только Base.Vector() для задания start_pnt и dir_normal а не кортежи

Как создать эллипс?

Создать эллипс можно несколькими путями:

Part.Ellipse()

Создает эллипс с большой полуосью 2 и малой полуосью 1 с центром в (0,0,0)

Part.Ellipse(Ellipse)

Создает копию данного эллипса

Part.Ellipse(S1,S2,Center)

Создаст эллипс с центров точке Center, где плоскость эллипса определяет Center, S1 и S2, это большая ось ззаданная Center и S1, это больший радиус расстояние между Center и S1, и меньший радиус это расстояние между S2 и юольшей осью.

Part.Ellipse(Center,MajorRadius,MinorRadius)

Создает эллипс с большим и меньшим радиусом MajorRadius и MinorRadius, и расположенным в плоскости заданной точкой Center и нормалью (0,0,1)


>>> eli = Part.Ellipse(Base.Vector(10,0,0),Base.Vector(0,5,0),Base.Vector(0,0,0))
>>> Part.show(eli.toShape())

в приведенном выше коде мы ввели S1, S2 и center. Аналогично Дуге, Эллипс также создает объект, а не ребро, так что мы должны превратить его в ребро используя toShape() для отображения

Примечание: Дуга допускает только Base.Vector() для задания точек, а не кортеж.


>>> eli = Part.Ellipse(Base.Vector(0,0,0),10,5)
>>> Part.show(eli.toShape())

Для верхнем конструкторе Эллипса мы ввели center, MajorRadius и MinorRadius

Как создать Тор?

makeTorus(radius1,radius2,[pnt,dir,angle1,angle2,angle]) -- Создает тор с указаными радиусами и углами. По умолчанию pnt=Vector(0,0,0),dir=Vector(0,0,1),angle1=0,angle1=360 и angle=360

Расмотрим тор как маленький круг, вытянутый вдоль большого круга:

radius1 это радиус большого круга, radius2 это радиус малого круга, pnt это центр тора и dir это направление нормали. angle1 и angle2 углы в радианах для малого круга, создаст дугу последний параметр angle создаст секцию(часть) тора:


>>> torus = Part.makeTorus(10, 2)

В коде выше, был создан тор с диаметром 20(радиус 10) и толщиной 4(малая окружность радиусом 2)


>>> tor=Part.makeTorus(10,5,Base.Vector(0,0,0),Base.Vector(0,0,1),0,180)

В приведенном выше коде, создан кусочек тора


>>> tor=Part.makeTorus(10,5,Base.Vector(0,0,0),Base.Vector(0,0,1),0,360,180)

В приведенном выше коде, создан полу тор, изменен только последний параметр т.е. angle а остальные углы установлены по умолчанию.

Подстановка угла 180 создаст тор от 0 до 180 т.е. половину

Как создать блок или паралелепипед?

makeBox(length,width,height,[pnt,dir]) -- Создает блок расположенный в pnt с размерами (length,width,height)

По умолчанию pnt=Vector(0,0,0) и dir=Vector(0,0,1)


>>> box = Part.makeBox(10,10,10)
>>> len(box.Vertexes)
8

Как создать Сферу?

makeSphere(radius,[pnt, dir, angle1,angle2,angle3]) -- Создает сферу с заданным радиусом. По умолчанию pnt=Vector(0,0,0), dir=Vector(0,0,1), angle1=-90, angle2=90 и angle3=360. angle1 и angle2 это вертиуальный минимум и максимум сферы(срезает часть сферы снизу или сверху), angle3 определяет замкнутое ли это тело вращения или его секция


>>> sphere = Part.makeSphere(10)
>>> hemisphere = Part.makeSphere(10,Base.Vector(0,0,0),Base.Vector(0,0,1),-90,90,180)

Как создать Цилиндр?

makeCylinder(radius,height,[pnt,dir,angle]) -- Создает цилиндр с указанным радиусом и высотой

По умолчанию pnt=Vector(0,0,0),dir=Vector(0,0,1) и angle=360


>>> cylinder = Part.makeCylinder(5,20)
>>> partCylinder = Part.makeCylinder(5,20,Base.Vector(20,0,0),Base.Vector(0,0,1),180)

Как создать Конус?

makeCone(radius1,radius2,height,[pnt,dir,angle]) -- Создает конус с указанными радиусами и высотой

По умолчанию pnt=Vector(0,0,0), dir=Vector(0,0,1) и angle=360


>>> cone = Part.makeCone(10,0,20)
>>> semicone = Part.makeCone(10,0,20,Base.Vector(20,0,0),Base.Vector(0,0,1),180)

Логические Операции

Как вырезать одну форму из других?

cut(...) - Вычисление различий задано в топологическом классе shape.


>>> cylinder = Part.makeCylinder(3,10,Base.Vector(0,0,0),Base.Vector(1,0,0))
>>> sphere = Part.makeSphere(5,Base.Vector(5,0,0))
>>> diff = cylinder.cut(sphere)
>>> diff.Solids
[<Solid object at 018AB630>, <Solid object at 0D8CDE48>]
>>> diff.ShapeType
'Compound'

Playground:cut shapes.png Playground:cut.png

Как получить пересечение двух форм?

common(...) - Пересечение задано в топологическом классе shape


>>> cylinder1 = Part.makeCylinder(3,10,Base.Vector(0,0,0),Base.Vector(1,0,0))
>>> cylinder2 = Part.makeCylinder(3,10,Base.Vector(5,0,-5),Base.Vector(0,0,1))
>>> common = cylinder1.common(cylinder2)

Playground:common cylinders.png Playground:common.png

Как объединить две формы?

fuse(...) - Объединение задано в топологическом классе shape


>>> cylinder1 = Part.makeCylinder(3,10,Base.Vector(0,0,0),Base.Vector(1,0,0))
>>> cylinder2 = Part.makeCylinder(3,10,Base.Vector(5,0,-5),Base.Vector(0,0,1))
>>> fuse = cylinder1.fuse(cylinder2)
>>> fuse.Solids
[<Solid object at 0DA5B8A0>]

Как получить сечение тела и заданой формы?

section(...) - Сечение задано в топологическом классе shape.

Вернет секущую кривую, состоящую из ребер


>>> cylinder1 = Part.makeCylinder(3,10,Base.Vector(0,0,0),Base.Vector(1,0,0))
>>> cylinder2 = Part.makeCylinder(3,10,Base.Vector(5,0,-5),Base.Vector(0,0,1))
>>> section = cylinder1.section(cylinder2)
>>> section.Wires
[]
>>> section.Edges
[<Edge object at 0D87CFE8>, <Edge object at 019564F8>, <Edge object at 0D998458>, 
 <Edge  object at 0D86DE18>, <Edge object at 0D9B8E80>, <Edge object at 012A3640>, 
 <Edge object at 0D8F4BB0>]

Playground:section.png

Исследование Форм

Вы легко можете исследовать структуру топологических данных:

import Part
b = Part.makeBox(100,100,100)
b.Wires
w = b.Wires[0]
w
w.Wires
w.Vertexes
Part.show(w)
w.Edges
e = w.Edges[0]
e.Vertexes
v = e.Vertexes[0]
v.Point

Если ввести строчку выше в интепритатор python , вы получите хорошее представление об устройстве Part объектов. Здесь, наша команда makeBox() создает твердое тело. Это тело, как и все Part тела, содержит грани. Грани, всегда содержат ломанные, которые являются набором ребер ограничивающих грань. Каждая грань обладает ровно одной замкнутой ломаной. В ломанной, мы можем посмотреть на отдельно на каждое ребро, и по краям каждого ребра , мы можем увидеть вершины. Очевидно, что прямые ребра обладают только двумя вершинами. Вершины модуля Part являются OCC(OpenCascade) формами, но они обладают атрибутом Point который возвращает FreeCAD вектор.

Исследование Рёбер

В случае ребра, которое является произвольной кривой, вы наверняка захотите произвести дискретизицию. В FreeCAD ребра задаются с помощью параметра длинны. Это означает что вы можете перемещатся вдоль ребра/кривой задавая длинну:

import Part
anEdge = Part.makeBox(100,100,100).Edges[0] # make a box with 100mm edge length и get the first edge
print anEdge.Length # get the length of the edge in mm (modeling unit)

Теперь вы получить доступ ко всем свойствам ребра, с помощью длинны или позиции. Это означает, что у ребра в 100mm длинной, начальная позиция это 0 а конечная это 100.

anEdge.tangentAt(0.0)      # касательная в начальной точке
anEdge.valueAt(0.0)        # Начальная точка
anEdge.valueAt(100.0)      # Конец ребра
anEdge.derivative1At(50.0) # Первая производная кривой в середине
anEdge.derivative2At(50.0) # Вторая производная по середине кривой
anEdge.derivative3At(50.0) # Третья производная кривой в средней точке
anEdge.centerOfCurvatureAt(50) # Расположение центра кривизны в данной позиции
anEdge.curvatureAt(50.0)   # кривизна
anEdge.normalAt(50)        # вектор нормали в данной точке(если он определен)

Использование выделения(выбора)

Здесь мы увидим как можно использовать "выделение", которое пользователь сделал в программе просмотра. прежде всего мы создадим блок и отобразим его в окне просмотра

import Part
Part.show(Part.makeBox(100,100,100))
Gui.SendMsgToActiveView("ViewFit")

Теперь выберем грани или ребра. С помощью этого сценария вы можете, поворить все выделенные объекты и их под элементы:

for o in Gui.Selection.getSelectionEx():
	print o.ObjectName
	for s in o.SubElementNames:
		print "name: ",s
	for s in o.SubObjects:
		print "object: ",s

Выделим несколько ребер и этот сценарий подсчитает их сумарную длину:

length = 0.0
for o in Gui.Selection.getSelectionEx():
	for s in o.SubObjects:
		length += s.Length

print "Length of the selected edges:" ,length

Примеры

Mesh Scripting/ru
Mesh to Part/ru
Available translations of this page: