| 28 | |
| 29 | == Predstavitev CAD-jedra Open CASCADE na primerih == |
| 30 | === Pregled uporabljenih OCC knjižnic === |
| 31 | {{{ |
| 32 | #!python |
| 33 | ## Importanje različnih knjižnic |
| 34 | |
| 35 | # Uporabniški vmesnik GUI |
| 36 | from OCC.Display.SimpleGui import * |
| 37 | |
| 38 | # Matematična knjižnica |
| 39 | import math |
| 40 | |
| 41 | # OpenCascade |
| 42 | from OCC.gp import * #točke |
| 43 | from OCC.BRepBuilderAPI import * #gradimo robove, segmente, mreže ... |
| 44 | from OCC.BRepPrimAPI import * #izdelava osnovnih geometrijskih primitivov |
| 45 | from OCC.BRepFilletAPI import * #izdelava zaokrožitev |
| 46 | }}} |
| 47 | |
| 48 | Točnejša navodila, opis funkcij in knjižnic lahko dobimo v PythonOCC dokumentaciji. |
| 49 | |
| 50 | === Inicializacija zaslona in izdelava grafičnega vmesnika=== |
| 51 | {{{ |
| 52 | #!python |
| 53 | # OCC.Display.SimpleGui.init_display() returns multiple |
| 54 | # values which are assigned here |
| 55 | display, start_display, add_menu, add_function_to_menu = \ |
| 56 | init_display() |
| 57 | draw_bottle() #kličemo CAD model, ki ga želimo prikazati na zaslonu |
| 58 | start_display() |
| 59 | }}} |
| 60 | === Risanje točk v prostoru === |
| 61 | Izdelava točk v prostoru je najosnovnejša operacija v OCC. |
| 62 | {{{ |
| 63 | #!python |
| 64 | # Definiranje začetnih točk |
| 65 | aPnt1 = gp_Pnt(-myWidth / 2. , 0 , 0) |
| 66 | aPnt2 = gp_Pnt(-myWidth / 2. , -myThickness / 4. , 0) |
| 67 | aPnt3 = gp_Pnt(0 , -myThickness / 2. , 0) |
| 68 | aPnt4 = gp_Pnt(myWidth / 2. , -myThickness / 4. , 0) |
| 69 | aPnt5 = gp_Pnt(myWidth / 2. , 0 , 0) |
| 70 | }}} |
| 71 | |
| 72 | === Izdelava robnih elementov === |
| 73 | V naslednjem koraku se iz začetnih točk izdela robove: |
| 74 | {{{ |
| 75 | #!python |
| 76 | # Definiranje geometrije |
| 77 | aArcOfCircle = GC_MakeArcOfCircle(aPnt2,aPnt3 ,aPnt4) |
| 78 | aSegment1 = GC_MakeSegment(aPnt1 , aPnt2) |
| 79 | aSegment2 = GC_MakeSegment(aPnt4 , aPnt5) |
| 80 | |
| 81 | # Definiranje topologije |
| 82 | aEdge1 = BRepBuilderAPI_MakeEdge(aSegment1.Value()) |
| 83 | aEdge2 = BRepBuilderAPI_MakeEdge(aArcOfCircle.Value()) |
| 84 | aEdge3 = BRepBuilderAPI_MakeEdge(aSegment2.Value()) |
| 85 | }}} |
| 86 | === Povezovanje robnih elementov v mreže === |
| 87 | Robne elemente se v nadaljevanju združi v mrežo. |
| 88 | {{{ |
| 89 | #!python |
| 90 | # Izdelava mreže |
| 91 | aWire = BRepBuilderAPI_MakeWire(aEdge1.Edge() , aEdge2.Edge() ,aEdge3.Edge()) |
| 92 | }}} |
| 93 | === Uporaba funkcij za izdelavo objektov v prostoru === |
| 94 | {{{ |
| 95 | #!python |
| 96 | # Izdelava celotnega profila - mirror |
| 97 | xAxis = gp_OX() |
| 98 | aTrsf = gp_Trsf() |
| 99 | aTrsf.SetMirror(xAxis) |
| 100 | aBRepTrsf = BRepBuilderAPI_Transform(aWire.Shape() , aTrsf) |
| 101 | aMirroredShape = aBRepTrsf.Shape() |
| 102 | aMirroredWire = TopoDS_wire(aMirroredShape) |
| 103 | mkWire = BRepBuilderAPI_MakeWire() |
| 104 | mkWire.Add(aWire.Wire()) |
| 105 | mkWire.Add(aMirroredWire) |
| 106 | myWireProfile = mkWire.Wire() |
| 107 | |
| 108 | # Telo: Iz profila se izdela telo (Funkcija izvleka 3D) |
| 109 | myFaceProfile = BRepBuilderAPI_MakeFace(myWireProfile) |
| 110 | aPrismVec = gp_Vec(0 , 0 , myHeight) |
| 111 | myBody = BRepPrimAPI_MakePrism(myFaceProfile.Face() , aPrismVec) |
| 112 | }}} |
| 113 | |
| 114 | === Risanje geometrijskih primitivov === |
| 115 | V OCC že obstajajo funkcije za izdelavo geometrijskih primitivov (kocka, valj,...), kar je prikazano na spodnjem primeru. |
| 116 | {{{ |
| 117 | #!python |
| 118 | from OCC.Display.SimpleGui import * |
| 119 | from OCC.BRepPrimAPI import * |
| 120 | |
| 121 | display, start_display, add_menu, add_function_to_menu = init_display() |
| 122 | my_box = BRepPrimAPI_MakeBox(10.,20.,30.).Shape() |
| 123 | # ali my_cylinder = BRepPrimAPI_MakeCylinder(neckAx2 , myNeckRadius , myNeckHeight), kjer so spremenljivke že preddefinirane |
| 124 | |
| 125 | display.DisplayShape(my_box) # ali display.DisplayShape(my_cylinder) |
| 126 | start_display() |
| 127 | }}} |
| 128 | === Izdelava primera Bottle z uporabo programskega jezika Python in knjižnice OCC === |
| 129 | Naslednji primer prikazuje izdelavo primera BottleCAD. Podrobnejši razdelek posameznih delov programske kode dobimo na [[http://trac.lecad.si/vaje/wiki/OpenCascade|MakeBottleCAD(C++)]]. |
| 130 | {{{ |
| 131 | #!python |
| 132 | ##Copyright 2011 Simon Kulovec (simon.kulovec@lecad.si) |
| 133 | ##Example: MakeCADBottle |
| 134 | ##This file is part of pythonOCC. |
| 135 | |
| 136 | ## Importanje različnih knjižnic |
| 137 | |
| 138 | # Uporabniški vmesnik GUI |
| 139 | from OCC.Display.SimpleGui import * |
| 140 | |
| 141 | # OpenCascade |
| 142 | from OCC.gp import * |
| 143 | from OCC.TopoDS import * |
| 144 | from OCC.GC import * |
| 145 | from OCC.BRepBuilderAPI import * |
| 146 | from OCC.BRepPrimAPI import * |
| 147 | from OCC.BRepFilletAPI import * |
| 148 | from OCC.BRepAlgoAPI import * |
| 149 | from OCC.Utils.Topology import * |
| 150 | from OCC.Geom import * |
| 151 | from OCC.Geom2d import * |
| 152 | from OCC.GCE2d import * |
| 153 | from OCC.BRep import * |
| 154 | from OCC.BRepLib import * |
| 155 | from OCC.BRepOffsetAPI import * |
| 156 | from OCC.TopTools import * |
| 157 | from OCC.TopAbs import * |
| 158 | from OCC.TopExp import * |
| 159 | |
| 160 | import math |
| 161 | |
| 162 | def show_bottle(aRes): |
| 163 | display.EraseAll() |
| 164 | print dir(display) |
| 165 | display.DisplayShape(aRes) |
| 166 | |
| 167 | def define_points(myWidth, myThickness, myHeight): |
| 168 | #Definiranje začetnih točk |
| 169 | aPnt1 = gp_Pnt(-myWidth / 2. , 0 , 0) |
| 170 | aPnt2 = gp_Pnt(-myWidth / 2. , -myThickness / 4. , 0) |
| 171 | aPnt3 = gp_Pnt(0 , -myThickness / 2. , 0) |
| 172 | aPnt4 = gp_Pnt(myWidth / 2. , -myThickness / 4. , 0) |
| 173 | aPnt5 = gp_Pnt(myWidth / 2. , 0 , 0) |
| 174 | |
| 175 | #Definiranje geometrije |
| 176 | aArcOfCircle = GC_MakeArcOfCircle(aPnt2,aPnt3 ,aPnt4) |
| 177 | aSegment1 = GC_MakeSegment(aPnt1 , aPnt2) |
| 178 | aSegment2 = GC_MakeSegment(aPnt4 , aPnt5) |
| 179 | |
| 180 | #Definiranje topologije |
| 181 | aEdge1 = BRepBuilderAPI_MakeEdge(aSegment1.Value()) |
| 182 | aEdge2 = BRepBuilderAPI_MakeEdge(aArcOfCircle.Value()) |
| 183 | aEdge3 = BRepBuilderAPI_MakeEdge(aSegment2.Value()) |
| 184 | aWire = BRepBuilderAPI_MakeWire(aEdge1.Edge() , aEdge2.Edge() ,aEdge3.Edge()) |
| 185 | |
| 186 | #Izdelava celotnega profila - mirror |
| 187 | xAxis = gp_OX() |
| 188 | aTrsf = gp_Trsf() |
| 189 | aTrsf.SetMirror(xAxis) |
| 190 | aBRepTrsf = BRepBuilderAPI_Transform(aWire.Shape() , aTrsf) |
| 191 | aMirroredShape = aBRepTrsf.Shape() |
| 192 | aMirroredWire = TopoDS_wire(aMirroredShape) |
| 193 | mkWire = BRepBuilderAPI_MakeWire() |
| 194 | mkWire.Add(aWire.Wire()) |
| 195 | mkWire.Add(aMirroredWire) |
| 196 | myWireProfile = mkWire.Wire() |
| 197 | |
| 198 | # Telo: Iz profila se izdela telo |
| 199 | myFaceProfile = BRepBuilderAPI_MakeFace(myWireProfile) |
| 200 | aPrismVec = gp_Vec(0 , 0 , myHeight) |
| 201 | myBody = BRepPrimAPI_MakePrism(myFaceProfile.Face() , aPrismVec) |
| 202 | |
| 203 | # Telo: Dodamo zaokrožitve (fillet) |
| 204 | mkFillet = BRepFilletAPI_MakeFillet(myBody.Shape()) |
| 205 | topology_traverser = Topo(myBody.Shape()) |
| 206 | for aEdge in topology_traverser.edges(): |
| 207 | mkFillet.Add(myThickness / 12. , aEdge) |
| 208 | myBody = mkFillet.Shape() |
| 209 | |
| 210 | #Dodajanje grla na steklenico |
| 211 | neckLocation = gp_Pnt(0, 0, myHeight) |
| 212 | neckNormal = gp_DZ() |
| 213 | neckAx2 = gp_Ax2(neckLocation, neckNormal) |
| 214 | |
| 215 | myNeckRadius = myThickness / 4 |
| 216 | myNeckHeight = myHeight / 10 |
| 217 | |
| 218 | mkCylinder = BRepPrimAPI_MakeCylinder(neckAx2 , myNeckRadius , \ |
| 219 | myNeckHeight) |
| 220 | myNeck = mkCylinder.Shape(); |
| 221 | |
| 222 | myBody = BRepAlgoAPI_Fuse(myBody, myNeck) |
| 223 | |
| 224 | # Izdelava votle steklenice |
| 225 | faceToRemove = None |
| 226 | zMax = -1; |
| 227 | t = Topo(myBody.Shape()) |
| 228 | k=1 |
| 229 | for aFace in t.faces(): |
| 230 | |
| 231 | aSurface = BRep_Tool().Surface(aFace) |
| 232 | |
| 233 | if aSurface.GetObject().IsInstance('Geom_Plane'): |
| 234 | aPlane = Handle_Geom_Plane().DownCast(aSurface).GetObject() |
| 235 | aPnt = aPlane.Location() |
| 236 | aZ = aPnt.Z() |
| 237 | if aZ>zMax: |
| 238 | faceToRemove = aFace |
| 239 | |
| 240 | facesToRemove = TopTools_ListOfShape() |
| 241 | facesToRemove.Append(faceToRemove) |
| 242 | myBody = BRepOffsetAPI_MakeThickSolid(myBody.Shape() , facesToRemove , \ |
| 243 | -myThickness/50 , 1.e-3) |
| 244 | |
| 245 | # Threading : Create Surfaces |
| 246 | aCyl1 = Geom_CylindricalSurface(gp_Ax3(neckAx2) , myNeckRadius * 0.99) |
| 247 | aCyl2 = Geom_CylindricalSurface(gp_Ax3(neckAx2) , myNeckRadius * 1.05) |
| 248 | |
| 249 | # Threading : Define 2D Curves |
| 250 | aPnt = gp_Pnt2d(2. * 3.141592 , myNeckHeight / 2.) |
| 251 | aDir = gp_Dir2d(2. * 3.141592 , myNeckHeight / 4.) |
| 252 | aAx2d = gp_Ax2d(aPnt , aDir) |
| 253 | |
| 254 | aMajor = 2. * 3.141592 |
| 255 | aMinor = myNeckHeight / 10. |
| 256 | |
| 257 | anEllipse1 = Geom2d_Ellipse(aAx2d , aMajor , aMinor) |
| 258 | anEllipse2 = Geom2d_Ellipse(aAx2d , aMajor , aMinor / 4) |
| 259 | |
| 260 | aArc2 = Geom2d_TrimmedCurve(anEllipse1.GetHandle() , 3.141592, 0.) |
| 261 | aArc1 = Geom2d_TrimmedCurve(anEllipse2.GetHandle() , 3.141592, 0.) |
| 262 | |
| 263 | anEllipsePnt2 = anEllipse1.Value(0.) |
| 264 | anEllipsePnt1 = anEllipse1.Value(3.141592) |
| 265 | |
| 266 | aSegment = GCE2d_MakeSegment(anEllipsePnt1 , anEllipsePnt2) |
| 267 | |
| 268 | # Threading : Build Edges and Wires |
| 269 | aEdge1OnSurf1 = BRepBuilderAPI_MakeEdge(aArc1.GetHandle() , aCyl1.GetHandle()) |
| 270 | aEdge2OnSurf1 = BRepBuilderAPI_MakeEdge(aSegment.Value() , aCyl1.GetHandle()) |
| 271 | aEdge1OnSurf2 = BRepBuilderAPI_MakeEdge(aArc2.GetHandle() , aCyl2.GetHandle()) |
| 272 | aEdge2OnSurf2 = BRepBuilderAPI_MakeEdge(aSegment.Value() , aCyl2.GetHandle()) |
| 273 | print dir(aEdge1OnSurf1) |
| 274 | threadingWire1 = BRepBuilderAPI_MakeWire(aEdge1OnSurf1.Edge() , aEdge2OnSurf1.Edge()) |
| 275 | threadingWire2 = BRepBuilderAPI_MakeWire(aEdge1OnSurf2.Edge() , aEdge2OnSurf2.Edge()) |
| 276 | |
| 277 | |
| 278 | BRepLib().BuildCurves3d(threadingWire1.Wire()) |
| 279 | BRepLib().BuildCurves3d(threadingWire2.Wire()) |
| 280 | |
| 281 | # Create Threading |
| 282 | aTool = BRepOffsetAPI_ThruSections(True) |
| 283 | |
| 284 | aTool.AddWire(threadingWire1.Wire()) |
| 285 | aTool.AddWire(threadingWire2.Wire()) |
| 286 | aTool.CheckCompatibility(False) |
| 287 | |
| 288 | myThreading = aTool.Shape() |
| 289 | |
| 290 | # Izdelava sestava |
| 291 | aRes = TopoDS_Compound() |
| 292 | |
| 293 | aBuilder = BRep_Builder() |
| 294 | aBuilder.MakeCompound (aRes) |
| 295 | |
| 296 | aBuilder.Add (aRes, myBody.Shape()) |
| 297 | aBuilder.Add (aRes, myThreading) |
| 298 | |
| 299 | # Izris oblike |
| 300 | show_bottle(aPnt1) |
| 301 | |
| 302 | def draw_bottle(event=None): |
| 303 | # Definiranje razdalj: širina, dolžina, višina |
| 304 | myWidth = 50.0 |
| 305 | myThickness = 30.0 |
| 306 | myHeight = 70.0 |
| 307 | # Define Points |
| 308 | define_points(myWidth, myThickness, myHeight) |
| 309 | |
| 310 | if __name__ == '__main__': |
| 311 | # OCC.Display.SimpleGui.init_display() returns multiple |
| 312 | # values which are assigned here |
| 313 | display, start_display, add_menu, add_function_to_menu = \ |
| 314 | init_display() |
| 315 | draw_bottle() #kličemo podprogram za izris bottle |
| 316 | start_display() |
| 317 | }}} |