| | 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 | }}} |