This page describes several methods for creating and modifying Part shapes from python. Before reading this page, if you are new to python, it is a good idea to read about python scripting and how python scripting works in FreeCAD.
We will here explain you how to control the Part Module directly from the FreeCAD python interpreter, or from any external script. The basics about Topological data scripting are described in Part Module Explaining the concepts. Be sure to browse the Scripting section and the FreeCAD Scripting Basics pages if you need more information about how python scripting works in FreeCAD.
Здесь мы объясним вам как управлять Модулем Деталей напрямую из интепритатора python FreeCAD, или из любого внешнего сценария. Для уверенности , просмотрите раздел Написание Сценариев и страницу Основ сценариев в FreeCAD если вам необходимо больше информации, о том как работает написание сценариев в FreeCAD.
Для первого использования функциональности модуля Деталей вы должны загрузить модуль Деталей в интепретатор:
import Part
Это UML обзор наиболее важных классов модуля Деталей:
Геометрические объекты являются строительными блоками для всех топологических объектов:
Доступны нижеследующие топологические типы данных:
Теперь мы создадим топологию из геометрических примитивов.
Для изучения мы используем деталь(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)
Создавая дугу из окружности мы создаем вспомогательную точку и создаем дугу через три точки:
VC1 = Base.Vector(-10,0,0) C1 = Part.Arc(V1,VC1,V4) # and the second one VC2 = Base.Vector(40,0,0) C2 = Part.Arc(V2,VC2,V3)
Линия может быть очень просто создана из точек:
L1 = Part.LineSegment(V1,V2) # and the second one L2 = Part.LineSegment(V3,V4)
Note: in FreeCAD 0.16 Part.Line was used, for FreeCAD 0.17 Part.LineSegment has to be used
Последний шаг собираем все основные геометрические элементы вместе и получаем форму:
S1 = Part.Shape([C1,L1,C2,L2])
Теперь вытягиваем ломанную по направлению и фактически получаем 3D форму:
W = Part.Wire(S1.Edges) P = W.extrude(Base.Vector(0,0,10))
Part.show(P)
Вы легко можете создать базовый топологический объект с помощью методов "make...()" содержащихся в модуле Деталей:
b = Part.makeBox(100,100,100) Part.show(b)
Куча других доступных make...() методов:
See the Part API page for a complete list of available methods of the Part module.
Сначала импортируем следующее:
import Part from FreeCAD import Base
Vectors are one of the most important pieces of information when building shapes. They contain a 3 numbers usually (but not necessarily always) the x, y and z cartesian coordinates. You create a vector like this:
myVector = Base.Vector(3,2,0)
We just created a vector at coordinates x=3, y=2, z=0. In the Part module, vectors are used everywhere. Part shapes also use another kind of point representation, called Vertex, which is acually nothing else than a container for a vector. You access the vector of a vertex like this:
myVertex = myShape.Vertexes[0] print myVertex.Point > Vector (3, 2, 0)
Ребра не что иное как линия с двумя вершинами:
edge = Part.makeLine((0,0,0), (10,0,0)) edge.Vertexes > [<Vertex object at 01877430>, <Vertex object at 014888E0>]
Примечание: Вы не можете создать ребро передав две вершины.
vec1 = Base.Vector(0,0,0) vec2 = Base.Vector(10,0,0) line = Part.LineSegment(vec1,vec2) edge = line.toShape()
Вы можете узнать длинну и центр ребра, вот так:
edge.Length > 10.0 edge.CenterOfMass > Vector (5, 0, 0)
So far we created an edge object, but it doesn't appear anywhere on screen. This is because we just manipulated python objects here. The FreeCAD 3D scene only displays what you tell it to display. To do that, we use this simple method:
Part.show(edge)
An object will be created in our FreeCAD document, and our "edge" shape will be attributed to it. Use this whenever it's time to display your creation on screen.
Ломанная может быть создана из списка ребер или даже из списка ломаных:
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)
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(c,0,pi)
Arcs are valid edges, like lines. So they can be used in wires too.
Линия по нескольким точкам, не что иное как создание ломаной с множеством ребер. функция makePolygon берет список точек и создает ломанную по этим точкам:
lshape_wire = Part.makePolygon([Base.Vector(0,5,0),Base.Vector(0,0,0),Base.Vector(5,0,0)])
Bézier curves are used to model smooth curves using a series of poles (points) and optional weights. The function below makes a Part.BezierCurve from a series of FreeCAD.Vector points. (Note: when "getting" and "setting" a single pole or weight indices start at 1, not 0.)
def makeBCurveEdge(Points): geomCurve = Part.BezierCurve() geomCurve.setPoles(Points) edge = Part.Edge(geomCurve) return(edge)
Плоскасть это ровная поверхность, в смысле 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)
There are several ways to modify shapes. Some are simple transformation operations such as moving or rotating shapes, other are more complex, such as unioning and subtracting one shape from another. Be aware that
Translating is the act of moving a shape from one place to another. Any shape (edge, face, cube, etc...) can be translated the same way:
myShape = Part.makeBox(2,2,2)
myShape.translate(Base.Vector(2,0,0))
This will move our shape "myShape" 2 units in the x direction.
To rotate a shape, you need to specify the rotation center, the axis, and the rotation angle:
myShape.rotate(Vector(0,0,0),Vector(0,0,1),180)
The above code will rotate the shape 180 degrees around the Z Axis.
A matrix is a very convenient way to store transformations in the 3D world. In a single matrix, you can set translation, rotation and scaling values to be applied to an object. For example:
myMat = Base.Matrix()
myMat.move(Base.Vector(2,0,0))
myMat.rotateZ(math.pi/2)
Note: FreeCAD matrixes work in radians. Also, almost all matrix operations that take a vector can also take 3 numbers, so those 2 lines do the same thing:
myMat.move(2,0,0)
myMat.move(Base.Vector(2,0,0))
When our matrix is set, we can apply it to our shape. FreeCAD provides 2 methods to do that: transformShape() and transformGeometry(). The difference is that with the first one, you are sure that no deformations will occur (see "scaling a shape" below). So we can apply our transformation like this:
myShape.trasformShape(myMat)
or
myShape.transformGeometry(myMat)
Scaling a shape is a more dangerous operation because, unlike translation or rotation, scaling non-uniformly (with different values for x, y and z) can modify the structure of the shape. For example, scaling a circle with a higher value horizontally than vertically will transform it into an ellipse, which behaves mathematically very differently. For scaling, we can't use the transformShape, we must use transformGeometry():
myMat = Base.Matrix()
myMat.scale(2,1,1)
myShape=myShape.transformGeometry(myMat)
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)
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)
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)
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>]
Extrusion is the act of "pushing" a flat shape in a certain direction resulting in a solid body. Think of a circle becoming a tube by "pushing it out":
circle = Part.makeCircle(10)
tube = circle.extrude(Base.Vector(0,0,2))
If your circle is hollow, you will obtain a hollow tube. If your circle is actually a disc, with a filled face, you will obtain a solid cylinder:
wire = Part.Wire(circle)
disc = Part.Face(wire)
cylinder = disc.extrude(Base.Vector(0,0,2))
Вы легко можете исследовать структуру топологических данных:
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
box = Part.makeBox(100,100,100)
anEdge = box.Edges[0]
print anEdge.Length
Теперь вы получить доступ ко всем свойствам ребра, с помощью длинны или позиции. Это означает, что у ребра в 100mm длинной, начальная позиция это 0 а конечная это 100.
anEdge.tangentAt(0.0) # tangent direction at the beginning
anEdge.valueAt(0.0) # Point at the beginning
anEdge.valueAt(100.0) # Point at the end of the edge
anEdge.derivative1At(50.0) # first derivative of the curve in the middle
anEdge.derivative2At(50.0) # second derivative of the curve in the middle
anEdge.derivative3At(50.0) # third derivative of the curve in the middle
anEdge.centerOfCurvatureAt(50) # center of the curvature for that position
anEdge.curvatureAt(50.0) # the curvature
anEdge.normalAt(50) # normal vector at that position (if defined)
Здесь мы увидим как можно использовать "выделение", которое пользователь сделал в программе просмотра. прежде всего мы создадим блок и отобразим его в окне просмотра
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
Типовой пример на 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.LineSegment(aPnt1,aPnt2)
aSegment2=Part.LineSegment(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.makeFillet(myThickness/12.0,myBody.Edges)
return myBody
el = makeBottle()
Part.show(el)
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.LineSegment(aPnt1,aPnt2)
aSegment2=Part.LineSegment(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, с помошью:
el = makeBottle()
Part.show(el)
или , ещё проще:
Here a complete example of building a box pierced.
The construction is done side by side and when the cube is finished, it is hollowed out of a cylinder through.
import Draft, Part, FreeCAD, math, PartGui, FreeCADGui, PyQt4
from math import sqrt, pi, sin, cos, asin
from FreeCAD import Base
size = 10
poly = Part.makePolygon( [ (0,0,0), (size, 0, 0), (size, 0, size), (0, 0, size), (0, 0, 0)])
face1 = Part.Face(poly)
face2 = Part.Face(poly)
face3 = Part.Face(poly)
face4 = Part.Face(poly)
face5 = Part.Face(poly)
face6 = Part.Face(poly)
myMat = FreeCAD.Matrix()
myMat.rotateZ(math.pi/2)
face2.transformShape(myMat)
face2.translate(FreeCAD.Vector(size, 0, 0))
myMat.rotateZ(math.pi/2)
face3.transformShape(myMat)
face3.translate(FreeCAD.Vector(size, size, 0))
myMat.rotateZ(math.pi/2)
face4.transformShape(myMat)
face4.translate(FreeCAD.Vector(0, size, 0))
myMat = FreeCAD.Matrix()
myMat.rotateX(-math.pi/2)
face5.transformShape(myMat)
face6.transformShape(myMat)
face6.translate(FreeCAD.Vector(0,0,size))
myShell = Part.makeShell([face1,face2,face3,face4,face5,face6])
mySolid = Part.makeSolid(myShell)
mySolidRev = mySolid.copy()
mySolidRev.reverse()
myCyl = Part.makeCylinder(2,20)
myCyl.translate(FreeCAD.Vector(size/2, size/2, 0))
cut_part = mySolidRev.cut(myCyl)
Part.show(cut_part)
Есть несколько путей чтобы сохранения вышей работы в 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")
To convert an .stp in .igs file simply :
import Part
s = Part.Shape()
s.read("file.stp") # incoming file igs, stp, stl, brep
s.exportIges("file.igs") # outbound file igs
Примечание этот импорт или открытие BREP, IGES or STEP файлов также можно сделать напрямую с помощью меню File -> Open or File -> Import. На данный момент экспорт ещё не включен, но будет там в ближайшее время.