wiki:occt

Version 8 (modified by dpenko, 5 years ago) (diff)

Premik 'Primer shranjevanja na SVN strežnik' iz pyOCCT strani na glavno stran od vaj.

Uporaba modula PythonOCCT

Projekt PythonOCCT je še ena priredba knjižnice OpenCASCADE 7.2.0 za programiranje v jeziku Python in je na voljo na strani https://github.com/LaughlinResearch/pyOCCT

Od PythonOCC-ja se razlikuje v verziji OpenCASCADE in v klicanju metod.

Primer kocke, ki je lahko poženemo v urejevalniku pycharm na strežiku viz.hpc.fs.uni-lj.si.

from OCCT.Visualization import BasicViewer
from OCCT.BRepPrimAPI import BRepPrimAPI_MakeBox
from OCCT.Graphic3d import Graphic3d_NOM_ALUMINIUM
v = BasicViewer()
v.set_white_background()
shape = BRepPrimAPI_MakeBox(10, 20, 30).Shape()
v.display_shape(shape, rgb=(0.8, 0.8, 0.5), material=Graphic3d_NOM_ALUMINIUM)
v.start()

Statične funkcije se v PythonOCC uvozijo kar na modularnem nivoju:

from OCC.TodoDS import topods_Edge

Med tem ko v PythonOCCT so statične funkcije znotraj razredov in imajo na koncu še podčrtaj

from OCCT.TopoDS import TopoDS
edge = TopoDS.Edge_(shape)

Prav tako se v PythonOCCT ne uporablja več metod GetHandle?, Downcast in GetObject?, ker se že v kodi PythonOCCT vse avtomatsko to naredi:

V PythonOCC

handle_geom = line.Copy()
new_line = Handle_Geom_Line.Downcast(handle_geom).GetObject()

V PythonOCCT

new_line = line.Copy()

To naredi stvari precej pitonične, saj lahko direktno ugotovimo tip geometrije z uporabo python metode isinstance:

# S pomočjo PythonOCC-ja preverimo če je TopoDS_Shape Geom_Plane.
hs = BRep_Tool_Surface(face)
downcast_result = Geom_Plane.DownCast(hs)
# Če je downcast_result tipa None, spremenljivka face ni Geom_Plane.
if downcast_result is None:
    return False
else:
    return True
# S pomočjo PythonOCCT-ja preverimo če je TopoDS_Shape Geom_Plane.
hs = BRep_Tool_Surface(face)
if isinstance(hs, Geom_Plane):
    return True
else:
    return False

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

Naslednji primer prikazuje izdelavo primera BottleCAD. Podrobnejši razdelek posameznih delov programske kode dobimo na MakeBottleCAD(C++). Za vizualizacijo se uporablja SALOME-8.5.0, ki se ga požene z ukayom smiter

Prikaz geometrije BottleCAD

##Uredil in posodobil 2018 Gregor Simic (gregor.simic@lecad.fs.uni-lj.si)
import math

# from OCCT.gp import gp_Pnt, gp_OX, gp_Vec, gp_Trsf, gp_DZ, gp_Ax2, gp_Ax3, gp_Pnt2d, gp_Dir2d, gp_Ax2d
from OCCT.gp import gp_Pnt, gp, gp_Vec, gp_Trsf, gp_Ax2, gp_Ax3, gp_Pnt2d, gp_Dir2d, gp_Ax2d
# Classes gp_OX, gp_DZ are statical methods and in OCCT stored inside
# OCCT.gp.gp as OX_ and DZ_ respectively.

from OCCT.GC import GC_MakeArcOfCircle, GC_MakeSegment
from OCCT.GCE2d import GCE2d_MakeSegment
from OCCT.Geom import Geom_Plane, Geom_CylindricalSurface, Geom_Surface
from OCCT.Geom2d import Geom2d_Ellipse, Geom2d_TrimmedCurve, Geom2d_Ellipse, Geom2d_Curve
from OCCT.BRepBuilderAPI import BRepBuilderAPI_MakeEdge, BRepBuilderAPI_MakeWire, BRepBuilderAPI_MakeFace, \
    BRepBuilderAPI_Transform
from OCCT.BRepPrimAPI import BRepPrimAPI_MakePrism, BRepPrimAPI_MakeCylinder
from OCCT.BRepFilletAPI import BRepFilletAPI_MakeFillet
from OCCT.BRepAlgoAPI import BRepAlgoAPI_Fuse
from OCCT.BRepOffsetAPI import BRepOffsetAPI_MakeThickSolid, BRepOffsetAPI_ThruSections

# from OCC.Core.BRepLib import breplib
# In OCCT the modules preserve the case.
from OCCT.BRepLib import BRepLib

# from OCC.Core.BRep import BRep_Tool_Surface, BRep_Builder
from OCCT.BRep import BRep_Tool, BRep_Builder
# OCCT does not have OCCT.Core but rather all modules are accessed directly
# from OCCT. Again BRep_Tool_Surface from OCC is a static method to create
# a Surface, hence in OCCT it is called from BRep_Tools as Surface_

from OCCT.TopoDS import TopoDS, TopoDS_Edge, TopoDS_Compound
from OCCT.TopExp import TopExp_Explorer
from OCCT.TopAbs import TopAbs_EDGE, TopAbs_FACE
from OCCT.TopTools import TopTools_ListOfShape

def face_is_plane(face):
    """
    Returns True if the TopoDS_Shape is a Geom_Plane, False otherwise.
    """
    hs = BRep_Tool.Surface_(face)
    # downcast_result = Geom_Plane.DownCast(hs)
    # OCCT 7.2.0 does not have the DownCast function anymore, in this case
    # we use we simply use the isinstance method to check if the shape
    # is a Geom_Plane.
    if isinstance(hs, Geom_Plane):
        return True
    else:
        # Othe cases when it returns false are, Geom_CylindricalSurface,
        # Geom_ToroidalSurface, Geom_SphericalSurface
        return False


def geom_plane_from_face(aFace):
    """
    Returns the geometric plane entity from a planar surface
    """
    # return Geom_Plane.DownCast(BRep_Tool.Surface_(aFace))
    return BRep_Tool.Surface_(aFace).Pln()


height = 70
width = 50
thickness = 30

print("creating bottle")
# The points we'll use to create the profile of the bottle's body
aPnt1 = gp_Pnt(-width / 2.0, 0, 0)
aPnt2 = gp_Pnt(-width / 2.0, -thickness / 4.0, 0)
aPnt3 = gp_Pnt(0, -thickness / 2.0, 0)
aPnt4 = gp_Pnt(width / 2.0, -thickness / 4.0, 0)
aPnt5 = gp_Pnt(width / 2.0, 0, 0)

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

# Could also construct the line edges directly using the points instead of the resulting line
aEdge1 = BRepBuilderAPI_MakeEdge(aSegment1.Value())
aEdge2 = BRepBuilderAPI_MakeEdge(aArcOfCircle.Value())
aEdge3 = BRepBuilderAPI_MakeEdge(aSegment2.Value())

# Create a wire out of the edges
aWire = BRepBuilderAPI_MakeWire(aEdge1.Edge(), aEdge2.Edge(), aEdge3.Edge())

# Quick way to specify the X axis
# xAxis = gp_OX() # From OCC
xAxis = gp.OX_()

# Set up the mirror
aTrsf = gp_Trsf()
aTrsf.SetMirror(xAxis)

# Apply the mirror transformation
aBRespTrsf = BRepBuilderAPI_Transform(aWire.Wire(), aTrsf)

# Get the mirrored shape back out of the transformation and convert back to a wire
aMirroredShape = aBRespTrsf.Shape()

# A wire instead of a generic shape now
# aMirroredWire = topods.Wire(aMirroredShape) # From OCC
aMirroredWire = TopoDS.Wire_(aMirroredShape)

# Combine the two constituent wires
mkWire = BRepBuilderAPI_MakeWire()
mkWire.Add(aWire.Wire())
mkWire.Add(aMirroredWire)
myWireProfile = mkWire.Wire()

# The face that we'll sweep to make the prism
myFaceProfile = BRepBuilderAPI_MakeFace(myWireProfile)

# We want to sweep the face along the Z axis to the height
aPrismVec = gp_Vec(0, 0, height)
myBody = BRepPrimAPI_MakePrism(myFaceProfile.Face(), aPrismVec)

# Add fillets to all edges through the explorer
mkFillet = BRepFilletAPI_MakeFillet(myBody.Shape())
anEdgeExplorer = TopExp_Explorer(myBody.Shape(), TopAbs_EDGE)

while anEdgeExplorer.More():
    anEdge = TopoDS.Edge_(anEdgeExplorer.Current())
    mkFillet.Add(thickness / 12.0, anEdge)

    anEdgeExplorer.Next()

myBody = mkFillet

# Create the neck of the bottle
neckLocation = gp_Pnt(0, 0, height)
# neckAxis = gp_DZ() # From OCC
neckAxis = gp.DZ_()
neckAx2 = gp_Ax2(neckLocation, neckAxis)

myNeckRadius = thickness / 4.0
myNeckHeight = height / 10.0

mkCylinder = BRepPrimAPI_MakeCylinder(neckAx2, myNeckRadius, myNeckHeight)

myBody = BRepAlgoAPI_Fuse(myBody.Shape(), mkCylinder.Shape())

# Our goal is to find the highest Z face and remove it
faceToRemove = None
zMax = -1

# We have to work our way through all the faces to find the highest Z face so we can remove it for the shell
aFaceExplorer = TopExp_Explorer(myBody.Shape(), TopAbs_FACE)
while aFaceExplorer.More():
    # aFace = topods.Face(aFaceExplorer.Current()) # From OCC
    aFace = TopoDS.Face_(aFaceExplorer.Current())

    if face_is_plane(aFace):
        aPlane = geom_plane_from_face(aFace)

        # We want the highest Z face, so compare this to the previous faces
        aPnt = aPlane.Location()
        aZ = aPnt.Z()
        if aZ > zMax:
            zMax = aZ
            faceToRemove = aFace

    aFaceExplorer.Next()

facesToRemove = TopTools_ListOfShape()
facesToRemove.Append(faceToRemove)

myBody = BRepOffsetAPI_MakeThickSolid(myBody.Shape(), facesToRemove, -thickness / 50.0, 0.001)

# Set up our surfaces for the threading on the neck
neckAx2_Ax3 = gp_Ax3(neckLocation, gp.DZ_())
aCyl1 = Geom_CylindricalSurface(neckAx2_Ax3, myNeckRadius * 0.99)
aCyl2 = Geom_CylindricalSurface(neckAx2_Ax3, myNeckRadius * 1.05)

# Set up the curves for the threads on the bottle's neck
aPnt = gp_Pnt2d(2.0 * math.pi, myNeckHeight / 2.0)
aDir = gp_Dir2d(2.0 * math.pi, myNeckHeight / 4.0)
anAx2d = gp_Ax2d(aPnt, aDir)

aMajor = 2.0 * math.pi
aMinor = myNeckHeight / 10.0

anEllipse1 = Geom2d_Ellipse(anAx2d, aMajor, aMinor)
anEllipse2 = Geom2d_Ellipse(anAx2d, aMajor, aMinor / 4.0)

anArc1 = Geom2d_TrimmedCurve(anEllipse1, 0, math.pi)
anArc2 = Geom2d_TrimmedCurve(anEllipse2, 0, math.pi)

anEllipsePnt1 = anEllipse1.Value(0)
anEllipsePnt2 = anEllipse1.Value(math.pi)

aSegment = GCE2d_MakeSegment(anEllipsePnt1, anEllipsePnt2)

# Build edges and wires for threading
anEdge1OnSurf1 = BRepBuilderAPI_MakeEdge(anArc1, aCyl1)
anEdge2OnSurf1 = BRepBuilderAPI_MakeEdge(aSegment.Value(), aCyl1)
anEdge1OnSurf2 = BRepBuilderAPI_MakeEdge(anArc2, aCyl2)
anEdge2OnSurf2 = BRepBuilderAPI_MakeEdge(aSegment.Value(), aCyl2)

threadingWire1 = BRepBuilderAPI_MakeWire(anEdge1OnSurf1.Edge(), anEdge2OnSurf1.Edge())
threadingWire2 = BRepBuilderAPI_MakeWire(anEdge1OnSurf2.Edge(), anEdge2OnSurf2.Edge())

# Compute the 3D representations of the edges/wires
# breplib.BuildCurves3d(threadingWire1.Shape()) # From OCC
# breplib.BuildCurves3d(threadingWire2.Shape()) # From OCC
BRepLib.BuildCurves3d_(threadingWire1.Shape())
BRepLib.BuildCurves3d_(threadingWire2.Shape())

# Create the surfaces of the threading
aTool = BRepOffsetAPI_ThruSections(True)
aTool.AddWire(threadingWire1.Wire())
aTool.AddWire(threadingWire2.Wire())
aTool.CheckCompatibility(False)
myThreading = aTool.Shape()

# Build the resulting compound
bottle = TopoDS_Compound()
aBuilder = BRep_Builder()
aBuilder.MakeCompound(bottle)
aBuilder.Add(bottle, myBody.Shape())
aBuilder.Add(bottle, myThreading)
print("bottle finished")

# if __name__ == "__main__":
#     from OCC.Display.SimpleGui import init_display
#     display, start_display, add_menu, add_function_to_menu = init_display()
#     display.DisplayColoredShape(bottle, update=True)
#     start_display()

# Display in GEOM
from GEOM_OCCT import fromPythonOCCT
fromPythonOCCT(bottle, 'bottle')

Zadnji dve vrstici preneseta geometrijski model v Geometry modul okolja SALOME. Funkcije GEOM_OCCT so razvite v LECAD-u in so del paketa SMITER.

Attachments (1)

Download all attachments as: .zip