poniedziałek, 17 maja 2010

FreeCAD i Python - od linii poleceń do kreatora...

Jedną z najmocniejszych stron FreeCADa jest interpreter Pythona. Widoczny jest on na dole okna, po wybraniu w menu View-Views-Python Console.

Pierwsza próba.
Po wklejeniu takiego kodu:
import Part
from FreeCAD import Base
cylinder1 = Part.makeCylinder(5,20,Base.Vector(20,0,0),Base.Vector(0,0,1),180)
Part.show(cylinder1)


Otrzymamy połowę walca - parametry w makeCylinder to: promień, wysokość, punkt startowy, kierunek (wektor jednostkowy), kąt obrotu.
Ostatnia linia odpowiada natomiast za wyświetlenie elementu.

Łączenie elementów
Kod który pozwolić wyświetlić cztery połączone (fuse) walce:
import Part
from FreeCAD import Base
cyl1 = Part.makeCylinder(5,15,Base.Vector(0,0,0),Base.Vector(1,0,0),360)
cyl2 = Part.makeCylinder(7,5,Base.Vector(15,0,0),Base.Vector(1,0,0),360)
cyl3 = Part.makeCylinder(6,7,Base.Vector(20,0,0),Base.Vector(1,0,0),360)
cyl4 = Part.makeCylinder(4,10,Base.Vector(27,0,0),Base.Vector(1,0,0),360)
fuse1 = cyl1.fuse(cyl2)
fuse1.Solids
fuse2 = fuse1.fuse(cyl3)
fuse2.Solids
fuse3 = fuse2.fuse(cyl4)
fuse3.Solids
Part.show(fuse3)

Należy zauważyć, że łączenie odbywa się po kolei a wyświetlanie wywoływane jest na samym końcu.



Szkic i wyciąganie
 Coś trudniejszego. Rysujemy dwa łuki i dwa odcinki, zaczynając od określenia położenia 6 (V1, V2, V3, V4, VC1, VC2) punktów (końce odcinków i łuków oraz "środki" łuków). Następnie łączymy odcinki i łuki (S1 = Part.Shape([C1,C2,L1,L2])) i tworzymy powierzchnię (F = Part.Face(W)). Wyciągamy powierzchnie by uzyskać bryłę (P = F.extrude(Base.Vector(0,0,10))). Trzy liczby w nawiasie decydują o kierunku i wysokości wyciągnięcia.
Kod:
import Part
from FreeCAD import Base
#punkty
V1 = Base.Vector(0,10,0)
V2 = Base.Vector(30,10,0)
V3 = Base.Vector(30,-10,0)
V4 = Base.Vector(0,-10,0)
#pierwszy łuk
VC1 = Base.Vector(-10,0,0)
C1 = Part.Arc(V1,VC1,V4)
#drugi łuk
VC2 = Base.Vector(40,0,0)
C2 = Part.Arc(V2,VC2,V3)
#linie
L1 = Part.Line(V1,V2)
L2 = Part.Line(V4,V3)
#polaczenie wszystkiego
S1 = Part.Shape([C1,C2,L1,L2])
#zamknieta linia
W = Part.Wire(S1.Edges)
#powierzchnia
F = Part.Face(W)
#wyciagniecie
P = F.extrude(Base.Vector(0,0,10))
Part.show(P)


Wszystko razem + wycinanie
Wycinając (różnica diff = fuse3.cut(P)) wyciągnięty kształt w naszym wałku otrzymujemy ładny wałek z rowkiem na wpust. By skrypt był bardziej uniwersalny, dodano odpowiednie zależności geometryczne.
Kod:
import Part
from FreeCAD import Base
#srednice
d1=20
d2=30
d3=40
d4=35
#dlugości
l1=40
l2=30
l3=35
l4=42
#wymiary rowka
g=5
sz=7
dl=25
#punkty dla rowka
x1=(l1+l2+l3+(l1+l2))/2-(dl/2)
x2=(l1+l2+l3+(l1+l2))/2+(dl/2)
y1=sz/2
y2=-sz/2
z=d3/2
xp=x1-sz/2
xk=x2+sz/2
#walki
cyl1 = Part.makeCylinder(d1/2,l1,Base.Vector(0,0,0),Base.Vector(1,0,0),360)
cyl2 = Part.makeCylinder(d2/2,l2,Base.Vector(l1,0,0),Base.Vector(1,0,0),360)
cyl3 = Part.makeCylinder(d3/2,l3,Base.Vector(l1+l2,0,0),Base.Vector(1,0,0),360)
cyl4 = Part.makeCylinder(d4/2,l4,Base.Vector(l1+l2+l3,0,0),Base.Vector(1,0,0),360)
fuse1 = cyl1.fuse(cyl2)
fuse1.Solids
fuse2 = fuse1.fuse(cyl3)
fuse2.Solids
fuse3 = fuse2.fuse(cyl4)
fuse3.Solids
#punkty
V1 = Base.Vector(x1,y1,z)
V2 = Base.Vector(x2,y1,z)
V3 = Base.Vector(x2,y2,z)
V4 = Base.Vector(x1,y2,z)
#pierwszy luk
VC1 = Base.Vector(xp,0,z)
C1 = Part.Arc(V1,VC1,V4)
#drugi luk
VC2 = Base.Vector(xk,0,z)
C2 = Part.Arc(V2,VC2,V3)
#linie
L1 = Part.Line(V1,V2)
L2 = Part.Line(V4,V3)
#polaczenie wszystkiego
S1 = Part.Shape([C1,C2,L1,L2])
#zamknieta linia
W = Part.Wire(S1.Edges)
#powierzchnia
F = Part.Face(W)
#wyciagniecie
P = F.extrude(Base.Vector(0,0,-g))
#roznica
diff = fuse3.cut(P)
diff.Solids
Part.show(diff)





Kreator
Ręczne wpisywanie kodu nie jest wygodne. Lepsze jest okienko z miejscami, gdzie możemy wpisać odpowiednie wartości. Trzeba tylko stworzyć autorski kreator.
Tu z pomocą przychodzi Qt Designer. Tworzymy tu okienko odpowiadające naszemu zmysłowi estetycznemu. Warto elementom nadać własne nazwy, np. przycisk nazwałem "przycisk":) Efekt zapisujemy jako plik *.ui, który konwertujemy:
pyuic4 walekokienko.ui > walekokienko.py

Otrzymany plik należy poddać odpowiednim modyfikacjom (dodane części kodu):

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'walekokienko.ui'
#
# Created: Mon May 17 17:13:56 2010
#      by: PyQt4 UI code generator 4.7.2
#
# WARNING! All changes made in this file will be lost!

from PyQt4 import QtCore, QtGui
import FreeCAD, Part
from FreeCAD import Base

class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(373, 436)
        self.przycisk = QtGui.QPushButton(Dialog)
        self.przycisk.setGeometry(QtCore.QRect(230, 370, 131, 61))
        self.przycisk.setObjectName("przycisk")
        self.sredn1 = QtGui.QLineEdit(Dialog)
        self.sredn1.setGeometry(QtCore.QRect(80, 90, 113, 25))
        self.sredn1.setObjectName("sredn1")
        self.sredn2 = QtGui.QLineEdit(Dialog)
        self.sredn2.setGeometry(QtCore.QRect(80, 120, 113, 25))
        self.sredn2.setObjectName("sredn2")
        self.sredn3 = QtGui.QLineEdit(Dialog)
        self.sredn3.setGeometry(QtCore.QRect(80, 150, 113, 25))
        self.sredn3.setObjectName("sredn3")
        self.sredn4 = QtGui.QLineEdit(Dialog)
        self.sredn4.setGeometry(QtCore.QRect(80, 180, 113, 25))
        self.sredn4.setObjectName("sredn4")
        self.label = QtGui.QLabel(Dialog)
        self.label.setGeometry(QtCore.QRect(80, 60, 57, 15))
        self.label.setObjectName("label")
        self.label_2 = QtGui.QLabel(Dialog)
        self.label_2.setGeometry(QtCore.QRect(46, 90, 21, 20))
        self.label_2.setObjectName("label_2")
        self.label_3 = QtGui.QLabel(Dialog)
        self.label_3.setGeometry(QtCore.QRect(46, 120, 21, 20))
        self.label_3.setObjectName("label_3")
        self.label_4 = QtGui.QLabel(Dialog)
        self.label_4.setGeometry(QtCore.QRect(46, 150, 21, 20))
        self.label_4.setObjectName("label_4")
        self.label_5 = QtGui.QLabel(Dialog)
        self.label_5.setGeometry(QtCore.QRect(47, 180, 20, 20))
        self.label_5.setObjectName("label_5")
        self.label_6 = QtGui.QLabel(Dialog)
        self.label_6.setGeometry(QtCore.QRect(220, 60, 57, 15))
        self.label_6.setObjectName("label_6")
        self.dlugosc1 = QtGui.QLineEdit(Dialog)
        self.dlugosc1.setGeometry(QtCore.QRect(200, 90, 113, 25))
        self.dlugosc1.setObjectName("dlugosc1")
        self.dlugosc2 = QtGui.QLineEdit(Dialog)
        self.dlugosc2.setGeometry(QtCore.QRect(200, 120, 113, 25))
        self.dlugosc2.setObjectName("dlugosc2")
        self.dlugosc3 = QtGui.QLineEdit(Dialog)
        self.dlugosc3.setGeometry(QtCore.QRect(200, 150, 113, 25))
        self.dlugosc3.setObjectName("dlugosc3")
        self.dlugosc4 = QtGui.QLineEdit(Dialog)
        self.dlugosc4.setGeometry(QtCore.QRect(200, 180, 113, 25))
        self.dlugosc4.setObjectName("dlugosc4")
        self.label_7 = QtGui.QLabel(Dialog)
        self.label_7.setGeometry(QtCore.QRect(80, 220, 57, 15))
        self.label_7.setObjectName("label_7")
        self.dlrow = QtGui.QLineEdit(Dialog)
        self.dlrow.setGeometry(QtCore.QRect(80, 240, 113, 25))
        self.dlrow.setObjectName("dlrow")
        self.szerrow = QtGui.QLineEdit(Dialog)
        self.szerrow.setGeometry(QtCore.QRect(80, 270, 113, 25))
        self.szerrow.setObjectName("szerrow")
        self.glerow = QtGui.QLineEdit(Dialog)
        self.glerow.setGeometry(QtCore.QRect(80, 300, 113, 25))
        self.glerow.setObjectName("glerow")
        self.label_8 = QtGui.QLabel(Dialog)
        self.label_8.setGeometry(QtCore.QRect(6, 240, 61, 20))
        self.label_8.setObjectName("label_8")
        self.label_9 = QtGui.QLabel(Dialog)
        self.label_9.setGeometry(QtCore.QRect(0, 270, 71, 16))
        self.label_9.setObjectName("label_9")
        self.label_10 = QtGui.QLabel(Dialog)
        self.label_10.setGeometry(QtCore.QRect(0, 300, 71, 16))
        self.label_10.setObjectName("label_10")

        self.retranslateUi(Dialog)
    QtCore.QObject.connect(self.przycisk,QtCore.SIGNAL("pressed()"),self.stworzWalek)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        Dialog.setWindowTitle(QtGui.QApplication.translate("Dialog", "Generator wałków", None, QtGui.QApplication.UnicodeUTF8))
        self.przycisk.setText(QtGui.QApplication.translate("Dialog", "Utwórz", None, QtGui.QApplication.UnicodeUTF8))
        self.label.setText(QtGui.QApplication.translate("Dialog", "Średnica", None, QtGui.QApplication.UnicodeUTF8))
        self.label_2.setText(QtGui.QApplication.translate("Dialog", "1", None, QtGui.QApplication.UnicodeUTF8))
        self.label_3.setText(QtGui.QApplication.translate("Dialog", "2", None, QtGui.QApplication.UnicodeUTF8))
        self.label_4.setText(QtGui.QApplication.translate("Dialog", "3", None, QtGui.QApplication.UnicodeUTF8))
        self.label_5.setText(QtGui.QApplication.translate("Dialog", "4", None, QtGui.QApplication.UnicodeUTF8))
        self.label_6.setText(QtGui.QApplication.translate("Dialog", "Długość", None, QtGui.QApplication.UnicodeUTF8))
        self.label_7.setText(QtGui.QApplication.translate("Dialog", "Rowek", None, QtGui.QApplication.UnicodeUTF8))
        self.label_8.setText(QtGui.QApplication.translate("Dialog", "Długość", None, QtGui.QApplication.UnicodeUTF8))
        self.label_9.setText(QtGui.QApplication.translate("Dialog", "Szerokość", None, QtGui.QApplication.UnicodeUTF8))
        self.label_10.setText(QtGui.QApplication.translate("Dialog", "Głębokość", None, QtGui.QApplication.UnicodeUTF8))

    def stworzWalek(self):
       try:
           # aprawsdzenie wpisanych licz
           d1 = float(self.sredn1.text())
           d2 = float(self.sredn2.text())
           d3 = float(self.sredn3.text())
           d4 = float(self.sredn4.text())
           l1 = float(self.dlugosc1.text())
           l2 = float(self.dlugosc2.text())
           l3 = float(self.dlugosc3.text())
           l4 = float(self.dlugosc4.text())
           sz = float(self.szerrow.text())
           g = float(self.glerow.text())
           dl = float(self.dlrow.text())
       except ValueError:
           print "Wpisz właściwe wartości!"
       else:
       #punkty dla rowka
       x1=(l1+l2+l3+(l1+l2))/2-(dl/2)
       x2=(l1+l2+l3+(l1+l2))/2+(dl/2)
       y1=sz/2
       y2=-sz/2
       z=d3/2
       xp=x1-sz/2
       xk=x2+sz/2
       #walki
       cyl1 = Part.makeCylinder(d1/2,l1,Base.Vector(0,0,0),Base.Vector(1,0,0),360)
       cyl2 = Part.makeCylinder(d2/2,l2,Base.Vector(l1,0,0),Base.Vector(1,0,0),360)
       cyl3 = Part.makeCylinder(d3/2,l3,Base.Vector(l1+l2,0,0),Base.Vector(1,0,0),360)
       cyl4 = Part.makeCylinder(d4/2,l4,Base.Vector(l1+l2+l3,0,0),Base.Vector(1,0,0),360)
       fuse1 = cyl1.fuse(cyl2)
       fuse1.Solids
       fuse2 = fuse1.fuse(cyl3)
       fuse2.Solids
       fuse3 = fuse2.fuse(cyl4)
       fuse3.Solids
       #punkty
       V1 = Base.Vector(x1,y1,z)
       V2 = Base.Vector(x2,y1,z)
       V3 = Base.Vector(x2,y2,z)
       V4 = Base.Vector(x1,y2,z)
       #pierwszy luk
       VC1 = Base.Vector(xp,0,z)
       C1 = Part.Arc(V1,VC1,V4)
       #drugi luk
       VC2 = Base.Vector(xk,0,z)
       C2 = Part.Arc(V2,VC2,V3)
       #linie
       L1 = Part.Line(V1,V2)
       L2 = Part.Line(V4,V3)
       #polaczenie wszystkiego
       S1 = Part.Shape([C1,C2,L1,L2])
       #zamknieta linia
       W = Part.Wire(S1.Edges)
       #powierzchnia
       F = Part.Face(W)
       #wyciagniecie
       P = F.extrude(Base.Vector(0,0,-g))
       #roznica
       diff = fuse3.cut(P)
       diff.Solids
       Part.show(diff)

class walek():
    d = QtGui.QWidget()
    d.ui = Ui_Dialog()
    d.ui.setupUi(d)
    d.show()

           



Prawidłowo sformatowane źródła (Python jest wrażliwy na wcięcia): py, ui.
Efekt:

Wcześniejsze posty o FC: wkupiesila.blogspot.com/2009/12/rozgryzamy-freecad-krok-po-kroku.html, wkupiesila.blogspot.com/2009/12/freecad-poznajemy-klawisz-f5.html


Dokładniejsze informacje - WIKI FreeCAD:

Brak komentarzy:

Prześlij komentarz