wiki:PythonOcc

Version 3 (modified by Leon Kos, 12 years ago) (diff)

--

PythonOCC omogoča enostavnejšo uporabo jedra modelirnika OpenCascade v jeziku Python. Prednost Pythona v primerjavi z C++ je:

  • Prenosljivosti. Programi se interpretirajo in jih ni potrebno prevajati zato delujejo na vseh operacijskih sistemih. So pa nekoliko pošasnejši.
  • Enostavnejša namestitev potrebnih knjižnic, brez zahtevne konfiguracije povezovalnih parametrov, ki so značilni za C++.
  • Lažje učenje jezika. V interaktivnem načinu obstaja tudi refleksija oziroma dinamično prepoznavanje možnih ukazov v objektu.

Za vaje je potrebno na Windowsih (tudi 63 bitnih) namestiti naslednje pakete:

  1. Python 2.6 interpreter jezika z osnovnimi knjižnicami
  2. wxPython za opravljanje z okni
  3. PythonOCC povezava Pytona z jedrom OpenCascade

Neobvezno vendar priporočljivo je namesti še:

  1. iPython za interektivno delo
  2. NumPy za delo z numeričnimi metodami in matrikami.
  3. SciPy za delo z znanstvenimi algoritmi.

Pred preizkusom prvih primerov je potrebno nastaviti še pot do interpreterja v Moj računalnik -> Lastnosti -> Dodatne nastavitve sistema -> Spremenljivke okolja ... -> Sistemske spremenljivke -> Path -> Uredi -> Vrednost spremeljivke: in na koncu dodamo ;c:\Python26;. Po tem je potremn računalnik vnovič zagnati.

V primeru, da nam klik na Start->Vsi programi->pythonOCC -> Examples -> Level1 -> HelloWorld -> helloworld.py okno na hitro odpre, vendar modela ne prikaže, imamo težave z OpenGL krmilniki. Najenostavneje težavo odpravimo s spremembo osnovnega prikazovalnika v datoteki C:\Python26\Lib\site-packages\OCC\Display\wxDisplay.py v kateri platformo darwin poistovetimo z win32 tako da del kode v tej datoteki izgleda:

if sys.platform=='win32':
    BaseClass = wx.Panel
else:
    import wx.glcanvas
    BaseClass = wx.glcanvas.GLCanvas

Predstavitev CAD-jedra Open CASCADE na primerih

Pregled uporabljenih OCC knjižnic

## Importanje različnih knjižnic

# Uporabniški vmesnik GUI
from OCC.Display.SimpleGui import *

# Matematična knjižnica
import math

# OpenCascade
from OCC.gp import * #točke
from OCC.BRepBuilderAPI import * #gradimo robove, segmente, mreže ...
from OCC.BRepPrimAPI import * #izdelava osnovnih geometrijskih primitivov
from OCC.BRepFilletAPI import * #izdelava zaokrožitev

Točnejša navodila, opis funkcij in knjižnic lahko dobimo v PythonOCC dokumentaciji.

Inicializacija zaslona in izdelava grafičnega vmesnika

# OCC.Display.SimpleGui.init_display() returns multiple
# values which are assigned here
display, start_display, add_menu, add_function_to_menu = \
init_display()
draw_bottle() #kličemo CAD model, ki ga želimo prikazati na zaslonu
start_display()

Risanje točk v prostoru

Izdelava točk v prostoru je najosnovnejša operacija v OCC.

# Definiranje začetnih točk
aPnt1 = gp_Pnt(-myWidth / 2. , 0 , 0)
aPnt2 = gp_Pnt(-myWidth / 2. , -myThickness / 4. , 0)
aPnt3 = gp_Pnt(0 , -myThickness / 2. , 0)
aPnt4 = gp_Pnt(myWidth / 2. , -myThickness / 4. , 0)
aPnt5 = gp_Pnt(myWidth / 2. , 0 , 0)

Izdelava robnih elementov

V naslednjem koraku se iz začetnih točk izdela robove:

# Definiranje geometrije
aArcOfCircle = GC_MakeArcOfCircle(aPnt2,aPnt3 ,aPnt4)
aSegment1 = GC_MakeSegment(aPnt1 , aPnt2)
aSegment2 = GC_MakeSegment(aPnt4 , aPnt5)

# Definiranje topologije
aEdge1 = BRepBuilderAPI_MakeEdge(aSegment1.Value())
aEdge2 = BRepBuilderAPI_MakeEdge(aArcOfCircle.Value())
aEdge3 = BRepBuilderAPI_MakeEdge(aSegment2.Value())

Povezovanje robnih elementov v mreže

Robne elemente se v nadaljevanju združi v mrežo.

# Izdelava mreže
aWire  = BRepBuilderAPI_MakeWire(aEdge1.Edge() , aEdge2.Edge() ,aEdge3.Edge())

Uporaba funkcij za izdelavo objektov v prostoru

# Izdelava celotnega profila - mirror
xAxis = gp_OX()
aTrsf = gp_Trsf()
aTrsf.SetMirror(xAxis)
aBRepTrsf = BRepBuilderAPI_Transform(aWire.Shape() , aTrsf)
aMirroredShape = aBRepTrsf.Shape()
aMirroredWire = TopoDS_wire(aMirroredShape)
mkWire = BRepBuilderAPI_MakeWire()
mkWire.Add(aWire.Wire())
mkWire.Add(aMirroredWire)
myWireProfile = mkWire.Wire()

# Telo: Iz profila se izdela telo (Funkcija izvleka 3D)
myFaceProfile = BRepBuilderAPI_MakeFace(myWireProfile)
aPrismVec = gp_Vec(0 , 0 , myHeight)
myBody = BRepPrimAPI_MakePrism(myFaceProfile.Face() , aPrismVec)

Risanje geometrijskih primitivov

V OCC že obstajajo funkcije za izdelavo geometrijskih primitivov (kocka, valj,...), kar je prikazano na spodnjem primeru.

from OCC.Display.SimpleGui import *
from OCC.BRepPrimAPI import *

display, start_display, add_menu, add_function_to_menu = init_display()
my_box = BRepPrimAPI_MakeBox(10.,20.,30.).Shape()
# ali my_cylinder = BRepPrimAPI_MakeCylinder(neckAx2 , myNeckRadius , myNeckHeight), kjer so spremenljivke že preddefinirane 

display.DisplayShape(my_box) # ali display.DisplayShape(my_cylinder)
start_display()

Izdelava primera Bottle z uporabo programskega jezika Python in knjižnice OCC

Naslednji primer prikazuje izdelavo primera BottleCAD. Podrobnejši razdelek posameznih delov programske kode dobimo na MakeBottleCAD(C++).

##Copyright 2011 Simon Kulovec (simon.kulovec@lecad.si)
##Example: MakeCADBottle
##This file is part of pythonOCC.

## Importanje različnih knjižnic

# Uporabniški vmesnik GUI
from OCC.Display.SimpleGui import *

# OpenCascade
from OCC.gp import *
from OCC.TopoDS import *
from OCC.GC import *
from OCC.BRepBuilderAPI import *
from OCC.BRepPrimAPI import *
from OCC.BRepFilletAPI import *
from OCC.BRepAlgoAPI import *
from OCC.Utils.Topology import *
from OCC.Geom import *
from OCC.Geom2d import *
from OCC.GCE2d import *
from OCC.BRep import *
from OCC.BRepLib import *
from OCC.BRepOffsetAPI import *
from OCC.TopTools import *
from OCC.TopAbs import *
from OCC.TopExp import *

import math

def show_bottle(aRes):
    display.EraseAll()
    print dir(display)
    display.DisplayShape(aRes)

def define_points(myWidth, myThickness, myHeight):
    #Definiranje začetnih točk
    aPnt1 = gp_Pnt(-myWidth / 2. , 0 , 0)
    aPnt2 = gp_Pnt(-myWidth / 2. , -myThickness / 4. , 0)
    aPnt3 = gp_Pnt(0 , -myThickness / 2. , 0)
    aPnt4 = gp_Pnt(myWidth / 2. , -myThickness / 4. , 0)
    aPnt5 = gp_Pnt(myWidth / 2. , 0 , 0)

    #Definiranje geometrije
    aArcOfCircle = GC_MakeArcOfCircle(aPnt2,aPnt3 ,aPnt4)
    aSegment1 = GC_MakeSegment(aPnt1 , aPnt2)
    aSegment2 = GC_MakeSegment(aPnt4 , aPnt5)

    #Definiranje topologije
    aEdge1 = BRepBuilderAPI_MakeEdge(aSegment1.Value())
    aEdge2 = BRepBuilderAPI_MakeEdge(aArcOfCircle.Value())
    aEdge3 = BRepBuilderAPI_MakeEdge(aSegment2.Value())
    aWire  = BRepBuilderAPI_MakeWire(aEdge1.Edge() , aEdge2.Edge() ,aEdge3.Edge())

    #Izdelava celotnega profila - mirror
    xAxis = gp_OX()
    aTrsf = gp_Trsf()
    aTrsf.SetMirror(xAxis)
    aBRepTrsf = BRepBuilderAPI_Transform(aWire.Shape() , aTrsf)
    aMirroredShape = aBRepTrsf.Shape()
    aMirroredWire = TopoDS_wire(aMirroredShape)
    mkWire = BRepBuilderAPI_MakeWire()
    mkWire.Add(aWire.Wire())
    mkWire.Add(aMirroredWire)
    myWireProfile = mkWire.Wire()

    # Telo: Iz profila se izdela telo
    myFaceProfile = BRepBuilderAPI_MakeFace(myWireProfile)
    aPrismVec = gp_Vec(0 , 0 , myHeight)
    myBody = BRepPrimAPI_MakePrism(myFaceProfile.Face() , aPrismVec)

    # Telo: Dodamo zaokrožitve (fillet)
    mkFillet = BRepFilletAPI_MakeFillet(myBody.Shape())
    topology_traverser = Topo(myBody.Shape())
    for aEdge in topology_traverser.edges():
        mkFillet.Add(myThickness / 12. , aEdge)
    myBody = mkFillet.Shape()

    #Dodajanje grla na steklenico
    neckLocation = gp_Pnt(0, 0, myHeight)
    neckNormal = gp_DZ()
    neckAx2 = gp_Ax2(neckLocation, neckNormal)

    myNeckRadius = myThickness / 4
    myNeckHeight = myHeight / 10

    mkCylinder = BRepPrimAPI_MakeCylinder(neckAx2 , myNeckRadius , \
                                          myNeckHeight)
    myNeck = mkCylinder.Shape();

    myBody = BRepAlgoAPI_Fuse(myBody, myNeck)

    # Izdelava votle steklenice
    faceToRemove = None
    zMax = -1;
    t = Topo(myBody.Shape())
    k=1
    for  aFace in t.faces():
    
        aSurface = BRep_Tool().Surface(aFace)
    
        if aSurface.GetObject().IsInstance('Geom_Plane'):
            aPlane = Handle_Geom_Plane().DownCast(aSurface).GetObject()
            aPnt = aPlane.Location()
            aZ = aPnt.Z()
            if aZ>zMax:
                faceToRemove = aFace

    facesToRemove = TopTools_ListOfShape()
    facesToRemove.Append(faceToRemove)
    myBody = BRepOffsetAPI_MakeThickSolid(myBody.Shape() , facesToRemove , \
                                          -myThickness/50 , 1.e-3)
    
    # Threading : Create Surfaces
    aCyl1 = Geom_CylindricalSurface(gp_Ax3(neckAx2) , myNeckRadius * 0.99)
    aCyl2 = Geom_CylindricalSurface(gp_Ax3(neckAx2) , myNeckRadius * 1.05)

    # Threading : Define 2D Curves
    aPnt = gp_Pnt2d(2. * 3.141592 , myNeckHeight / 2.)
    aDir = gp_Dir2d(2. * 3.141592 , myNeckHeight / 4.)
    aAx2d = gp_Ax2d(aPnt , aDir)
        
    aMajor = 2. * 3.141592
    aMinor = myNeckHeight / 10.
    
    anEllipse1 = Geom2d_Ellipse(aAx2d , aMajor , aMinor)
    anEllipse2 = Geom2d_Ellipse(aAx2d , aMajor , aMinor / 4)

    aArc2 = Geom2d_TrimmedCurve(anEllipse1.GetHandle() , 3.141592, 0.)
    aArc1 = Geom2d_TrimmedCurve(anEllipse2.GetHandle() , 3.141592, 0.)

    anEllipsePnt2 = anEllipse1.Value(0.)
    anEllipsePnt1 = anEllipse1.Value(3.141592)
    
    aSegment = GCE2d_MakeSegment(anEllipsePnt1 , anEllipsePnt2)

    # Threading : Build Edges and Wires
    aEdge1OnSurf1 = BRepBuilderAPI_MakeEdge(aArc1.GetHandle() , aCyl1.GetHandle())
    aEdge2OnSurf1 = BRepBuilderAPI_MakeEdge(aSegment.Value() , aCyl1.GetHandle())
    aEdge1OnSurf2 = BRepBuilderAPI_MakeEdge(aArc2.GetHandle() , aCyl2.GetHandle())
    aEdge2OnSurf2 = BRepBuilderAPI_MakeEdge(aSegment.Value() , aCyl2.GetHandle())
    print dir(aEdge1OnSurf1)
    threadingWire1 = BRepBuilderAPI_MakeWire(aEdge1OnSurf1.Edge() , aEdge2OnSurf1.Edge())
    threadingWire2 = BRepBuilderAPI_MakeWire(aEdge1OnSurf2.Edge() , aEdge2OnSurf2.Edge())


    BRepLib().BuildCurves3d(threadingWire1.Wire())
    BRepLib().BuildCurves3d(threadingWire2.Wire())

    # Create Threading
    aTool = BRepOffsetAPI_ThruSections(True)

    aTool.AddWire(threadingWire1.Wire())
    aTool.AddWire(threadingWire2.Wire())
    aTool.CheckCompatibility(False)

    myThreading = aTool.Shape()

    # Izdelava sestava
    aRes = TopoDS_Compound()

    aBuilder = BRep_Builder()
    aBuilder.MakeCompound (aRes)

    aBuilder.Add (aRes, myBody.Shape())
    aBuilder.Add (aRes, myThreading)

    # Izris oblike
    show_bottle(aPnt1)

def draw_bottle(event=None):
    # Definiranje razdalj: širina, dolžina, višina
    myWidth = 50.0
    myThickness = 30.0
    myHeight = 70.0
    # Define Points
    define_points(myWidth, myThickness, myHeight)
    
if __name__ == '__main__':
    # OCC.Display.SimpleGui.init_display() returns multiple
    # values which are assigned here
    display, start_display, add_menu, add_function_to_menu = \
    init_display()
    draw_bottle() #kličemo podprogram za izris bottle
    start_display()

Attachments (11)