Программирование топологических данных
Введение
Здесь мы объясним вам как управлять Модулем Деталей напрямую из интепритатора python FreeCAD, или из любого внешнего сценария. Для уверенности , просмотрите раздел Написание Сценариев и страницу Основ сценариев в FreeCAD если вам необходимо больше информации, о том как работает написание сценариев в FreeCAD.
Для первого использования функциональности модуля Деталей вы должны загрузить модуль Деталей в интепретатор:
import Part
Диаграмма Классов
Это UML обзор наиболее важных классов модуля Деталей:
Геометрия
Геометрические объекты являются строительными блоками для всех топологических объектов:
- 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>]
Исследование Форм
Вы легко можете исследовать структуру топологических данных:
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
Примеры
Создание простейшей топологии
Теперь мы создадим топологию из геометрических примитивов. Для изучения мы используем деталь(part) , как показано на картинке состоящую из четырех вершин, двух окружностей и двух линий.
Создание Геометрии
сначала мы должны создать отдельную деталь из данной ломаной. И мы должны убедиться что вершины геометрических частей расположены на тех же позициях. В противном случае позже мы не смогли бы соеденить геометрические части в топологию!
Так мы создаем новые точки:
from FreeCAD import Base V1 = Base.Vector(0,10,0) V2 = Base.Vector(30,10,0) V3 = Base.Vector(30,-10,0) V4 = Base.Vector(0,-10,0)
Arc
Создавая дугу из окружности мы создаем вспомогательную точку и создаем дугу через три точки:
VC1 = Base.Vector(-10,0,0) C1 = Part.Arc(V1,VC1,V4) # и the second one VC2 = Base.Vector(40,0,0) C2 = Part.Arc(V2,VC2,V3)
Line
Линия может быть очень просто создана из точек:
L1 = Part.Line(V1,V2) # и the second one L2 = Part.Line(V4,V3)
Соединяем все вместе
Последний шаг собираем все основные геометрические элементы вместе и получаем форму:
S1 = Part.Shape([C1,C2,L1,L2])
Создание призмы
Теперь вытягиваем ломанную по направлению и фактически получаем 3D форму:
W = Part.Wire(S1.Edges) P = W.extrude(Base.Vector(0,0,10))
OCC бутыль
Типовой пример на OpenCasCade Getting Started Page можно узнать как построить бутыль. Также это отличный пример для FreeCAD. В самом деле вы можете последовать нашему примеру изложенному ниже и странице OCC одновременно, вы лучше поймете как реализованы OCC структуры в FreeCAD.
Готовый сценарий описанный ниже, также включен в установленный FreeCAD (в папке Mod/Part ) и может быть вызван интепритатором python, вводом:
import Part import MakeBottle bottle = MakeBottle.makeBottle() Part.show(bottle)
Готовый сценарий
Здесь представлен готовый сценарий MakeBottle:
import Part, FreeCAD, math from FreeCAD import Base def makeBottle(myWidth=50.0, myHeight=70.0, myThickness=30.0): aPnt1=Base.Vector(-myWidth/2.,0,0) aPnt2=Base.Vector(-myWidth/2.,-myThickness/4.,0) aPnt3=Base.Vector(0,-myThickness/2.,0) aPnt4=Base.Vector(myWidth/2.,-myThickness/4.,0) aPnt5=Base.Vector(myWidth/2.,0,0) aArcOfCircle = Part.Arc(aPnt2,aPnt3,aPnt4) aSegment1=Part.Line(aPnt1,aPnt2) aSegment2=Part.Line(aPnt4,aPnt5) aEdge1=aSegment1.toShape() aEdge2=aArcOfCircle.toShape() aEdge3=aSegment2.toShape() aWire=Part.Wire([aEdge1,aEdge2,aEdge3]) aTrsf=Base.Matrix() aTrsf.rotateZ(math.pi) # rotate around the z-axis aMirroredWire=aWire.transformGeometry(aTrsf) myWireProfile=Part.Wire([aWire,aMirroredWire]) myFaceProfile=Part.Face(myWireProfile) aPrismVec=Base.Vector(0,0,myHeight) myBody=myFaceProfile.extrude(aPrismVec) myBody=myBody.makeFillet(myThickness/12.0,myBody.Edges) neckLocation=Base.Vector(0,0,myHeight) neckNormal=Base.Vector(0,0,1) myNeckRadius = myThickness / 4. myNeckHeight = myHeight / 10 myNeck = Part.makeCylinder(myNeckRadius,myNeckHeight,neckLocation,neckNormal) myBody = myBody.fuse(myNeck) faceToRemove = 0 zMax = -1.0 for xp in myBody.Faces: try: surf = xp.Surface if type(surf) == Part.Plane: z = surf.Position.z if z > zMax: zMax = z faceToRemove = xp except: continue myBody = myBody.makeThickness([faceToRemove],-myThickness/50 , 1.e-3) return myBody
Подробные объяснения
import Part, FreeCAD, math from FreeCAD import Base
Нам ,конечно, необходимы Part модуль, а также FreeCAD.Base модуль, который содержит основные структуры FreeCAD такие как векторы и матрицы.
def makeBottle(myWidth=50.0, myHeight=70.0, myThickness=30.0): aPnt1=Base.Vector(-myWidth/2.,0,0) aPnt2=Base.Vector(-myWidth/2.,-myThickness/4.,0) aPnt3=Base.Vector(0,-myThickness/2.,0) aPnt4=Base.Vector(myWidth/2.,-myThickness/4.,0) aPnt5=Base.Vector(myWidth/2.,0,0)
Здесь мы задаем нашу функцию makeBottle. Эта функция может быть вызвана без аргументов, как мы делали выше, в этом случае будут использоваться значения по умолчанию для ширины, высоты и толщины. Затем мы определили несколько точек которые будут использоваться для построения базового сечения.
aArcOfCircle = Part.Arc(aPnt2,aPnt3,aPnt4) aSegment1=Part.Line(aPnt1,aPnt2) aSegment2=Part.Line(aPnt4,aPnt5)
Здесь мы фактически задаём геометрию: дугу, созданую по 3 точкам, и два линейных сегменты, созданные по 2 точкам.
aEdge1=aSegment1.toShape() aEdge2=aArcOfCircle.toShape() aEdge3=aSegment2.toShape() aWire=Part.Wire([aEdge1,aEdge2,aEdge3])
Запомнили раличие между геометрией и формой? Здесь мы создаем форму из нашей строительной геометрии 3 рёбер (ребра могут быть прямыми или кривыми), затем из рёбер создается ломанная.
aTrsf=Base.Matrix() aTrsf.rotateZ(math.pi) # rotate around the z-axis aMirroredWire=aWire.transformGeometry(aTrsf) myWireProfile=Part.Wire([aWire,aMirroredWire])
На данный момент мы построили только половину сечения. Проще, чем строить таким же образом целое сечение, мы можем просто отразить то что мы сделали и склеить две половинки. Сначала создадим матрицу(Нео ау). Матрица является распространенным способом произвести изменения над объектом в 3D пространстве, также она может содержать в одной структуре все базовые преобразования которые позволяют 3D объекты(перемещение, вращение и масштабирование). Здесь , после создания матрицы, мы отражаем её и создаем копию нашеё ломанной, применя к ней преобразование матрицой. Теперь мы получили две ломанные и мы можем создать из них третью ломаную, так как ломанные это всего лишь список ребер.
myFaceProfile=Part.Face(myWireProfile) aPrismVec=Base.Vector(0,0,myHeight) myBody=myFaceProfile.extrude(aPrismVec) myBody=myBody.makeFillet(myThickness/12.0,myBody.Edges)
Теперь мы получили замкнутую ломаную, которую можно обратить в грань. После мы получили грань, мы можем вытянуть её. Сделаа это ,мы действительно получим твердое тело. Теперь мы добавим небольшое скругление к нашему объекту, потому что мы заботимся о качественном дизайне, разве нет?
neckLocation=Base.Vector(0,0,myHeight) neckNormal=Base.Vector(0,0,1) myNeckRadius = myThickness / 4. myNeckHeight = myHeight / 10 myNeck = Part.makeCylinder(myNeckRadius,myNeckHeight,neckLocation,neckNormal)
Теперь когда тело нашей бутыли создано, нам нужно создать горлышко. Так мы создаем новое твердое тело ,это цилиндр.
myBody = myBody.fuse(myNeck)
Очень мощная операция слияния, которая обычно называется в других приложениях объединением. Она заботится о склеивании, о том что должно быть приклено и удаляет детали которые нужно удалить.
return myBody
Теперь мы получаем нашу твердотельную Деталь как результат нашей функции. Это Деталь - твердотельная, как и любая другая Деталь форма, может быть свзана с объектом в документе FreeCAD, с помошью:
myObject = FreeCAD.ActiveDocument.addObject("Part::Feature","myObject") myObject.Shape = bottle
или , ещё проще:
Part.show(bottle)
Загрузка и Сохранение
Есть несколько путей чтобы сохранения вышей работы в Part модули. Вы конечно можете сохранить ваш FreeCAD документ, а также вы можете сохранить Part(Деталь) объект напрямую в обычные CAD форматы, такие как BREP, IGS, STEP и STL.
Сохраненить форму в файл , легко. Есть доступные для всех форм методы exportBrep(), exportIges(), exportStl() и exportStep() . Таким образом:
import Part s = Part.makeBox(0,0,0,10,10,10) s.exportStep("test.stp")
это сохранит наш блок в файл формата STEP. Для загрузки BREP, IGES или STEP файлов, просто сделайте наоборот:
import Part s = Part.Shape() s.read("test.stp")
Примечание этот импорт или открытие BREP, IGES or STEP файлов также можно сделать напрямую с помощью меню File -> Open or File -> Import. На данный момент экспорт ещё не включен, но будет там в ближайшее время.