Package empro :: Package toolkit :: Package geometry
[frames] | no frames]

Source Code for Package empro.toolkit.geometry

  1  # Copyright 1983-2019 Keysight Technologies, Keysight Confidential 
  2  from empro.geometry import * 
  3  import math 
  4  import string 
  5  import base64 
  6  import tempfile 
  7   
  8  # operations 
9 -def __translate(iObject, iVector):
10 if isinstance(iObject,Assembly): 11 for i in range(len(iObject)): 12 __translate(iObject[i],iVector) 13 else: 14 iObject.coordinateSystem.translate(iVector)
15
16 -def translate(iObject, iVector):
17 __translate(iObject, iVector) 18 return iObject
19
20 -def __canonicalUnit(iObject, iCanonicalUnit):
21 if isinstance(iObject,Assembly): 22 for i in range(len(iObject)): 23 __canonicalUnit(iObject[i],iCanonicalUnit) 24 else: 25 # also move to absolute coordinate system 26 v = iObject.coordinateSystem.anchorPoint.asVector3d() 27 mv = iObject.coordinateSystem.transformDirection(v, "ReferenceToLocal") 28 iObject.coordinateSystem.translate(mv) 29 iObject.coordinateSystem.anchorPoint = Vector3d(0,0,0) 30 iObject.scale(iObject.unit.toReferenceUnits(1.0)/iCanonicalUnit.toReferenceUnits(1.0))
31
32 -def canonicalUnit(iObject,iUnitAbbrev="m"):
33 import empro 34 _canonicalUnit = empro.units.unitByAbbreviation(iUnitAbbrev) 35 __canonicalUnit(iObject, _canonicalUnit) 36 return iObject
37
38 -def __deCanonicalUnit(iObject,iDecanonicalUnit):
39 if isinstance(iObject,Assembly): 40 for i in range(len(iObject)): 41 __deCanonicalUnit(iObject[i],iDecanonicalUnit) 42 else: 43 iObject.scale(iObject.unit.fromReferenceUnits(1.0)/iDecanonicalUnit.fromReferenceUnits(1.0))
44
45 -def deCanonicalUnit(iObject,iUnitAbbrev="m"):
46 import empro 47 _decanonicalUnit = empro.units.unitByAbbreviation(iUnitAbbrev) 48 __deCanonicalUnit(iObject,_decanonicalUnit) 49 return iObject
50
51 -def __matchCoordinateSystems(source,target):
52 pass
53
54 -def scale(iObject,iFactor):
55 if isinstance(iObject, Assembly): 56 for i in range(len(iObject)): 57 scale(iObject[i], iFactor) 58 else: 59 return iObject.scale(iFactor)
60 61 # 3D primitives
62 -def Wire(iFrom,iTo):
63 """ 64 Wire(iFrom, iTo) 65 Returns a straight wire object. 66 @type iFrom: L{Vector3d} 67 @param iFrom: start point of the wire 68 @type iTo: L{Vector3d} 69 @param iTo: end point of the wire 70 @rtype: L{Part} 71 @return: the wire object as L{Part} 72 """ 73 s = Sketch() 74 s.add(Line(iFrom,iTo)) 75 return s
76
77 -def __zBlock(iFrom,iTo):
78 s = Sketch() 79 lines = [] 80 corners = [Vector3d(iFrom.x,iFrom.y,0),Vector3d(iTo.x,iFrom.y,0), 81 Vector3d(iTo.x,iTo.y,0),Vector3d(iFrom.x,iTo.y,0)] 82 for i in range(len(corners)): 83 s.addEdge(Line(corners[i-1],corners[i])) 84 extrude = Extrude(s,iTo.z-iFrom.z) 85 m = Model() 86 m.recipe = Recipe() 87 m.recipe.append(extrude) 88 m.coordinateSystem.translate(Vector3d(0,0,iFrom.z)) 89 return m
90 91
92 -def Block(iFrom,iTo):
93 """ 94 Block(iFrom, iTo) 95 Returns a rectangular block defined by the two opposing points iFrom and iTo. 96 @type iFrom: L{Vector3d} 97 @param iFrom: first corner of the rectangular block 98 @type iTo: L{Vector3d} 99 @param iTo: opposing point of the rectangular block 100 @rtype: L{Model} 101 @return: the rectangular block 102 """ 103 return __zBlock(iFrom,iTo)
104
105 -def xCylinder(iInnerRadius, iOuterRadius, iBottomCenter, iHeight):
106 """ 107 xCylinder(iInnerRadius, iOuterRadius, iBottomCenter, iHeight) 108 Returns a cylinder whose axis is X-directed. 109 @type iInnerRadius: float 110 @param iInnerRadius: inner radius of the cylinder 111 @type iOuterRadius: float 112 @param iOuterRadius: outer radius of the cylinder 113 @type iBottomCenter: L{Vector3d} 114 @param iBottomCenter: center of the bottom of the cylinder 115 @type iHeight: float 116 @param iHeight: height of the cylinder 117 @rtype: L{Part} 118 @return: the cylinder as L{Part} 119 """ 120 m = zCylinder(iInnerRadius, iOuterRadius, iBottomCenter, iHeight) 121 m.coordinateSystem.rotate(0.0,math.pi/2.0,0.0) 122 return m
123
124 -def yCylinder(iInnerRadius, iOuterRadius, iBottomCenter, iHeight):
125 """ 126 yCylinder(iInnerRadius, iOuterRadius, iBottomCenter, iHeight) 127 Returns a cylinder whose axis is Y-directed. 128 @type iInnerRadius: float 129 @param iInnerRadius: inner radius of the cylinder 130 @type iOuterRadius: float 131 @param iOuterRadius: outer radius of the cylinder 132 @type iBottomCenter: L{Vector3d} 133 @param iBottomCenter: center of the bottom of the cylinder 134 @type iHeight: float 135 @param iHeight: height of the cylinder 136 @rtype: L{Part} 137 @return: the cylinder as L{Part} 138 """ 139 m = zCylinder(iInnerRadius, iOuterRadius, iBottomCenter, iHeight) 140 m.coordinateSystem.rotate(math.pi/2.0,0.0,0.0) 141 return m
142
143 -def zCylinder(iInnerRadius, iOuterRadius, iBottomCenter, iHeight):
144 """ 145 zCylinder(iInnerRadius, iOuterRadius, iBottomCenter, iHeight) 146 Returns a cylinder whose axis is Z-directed. 147 @type iInnerRadius: float 148 @param iInnerRadius: inner radius of the cylinder 149 @type iOuterRadius: float 150 @param iOuterRadius: outer radius of the cylinder 151 @type iBottomCenter: L{Vector3d} 152 @param iBottomCenter: center of the bottom of the cylinder 153 @type iHeight: float 154 @param iHeight: height of the cylinder 155 @rtype: L{Part} 156 @return: the cylinder as L{Part} 157 """ 158 import empro 159 m = Model() 160 m.recipe = Recipe() 161 irValue = float(empro.core.Expression(iInnerRadius)) 162 if irValue > 0.0 : 163 s = Sketch() # during extrusion the Sketch is used as _relative_ geometry 164 bottomCenter = Vector3d(0.0,0.0,0.0) 165 s.addEdge( zCircle(bottomCenter, iInnerRadius) ) 166 s.addEdge( zCircle(bottomCenter, iOuterRadius) ) 167 sweep = Extrude( s, iHeight ) 168 m.recipe.append( sweep ) 169 else : # iInnerRadius == 0 -> use primitive components (cylinder) 170 libcmpnt = empro.geometry.Cylinder(iHeight, iOuterRadius, iOuterRadius) 171 m.recipe.append(libcmpnt) 172 m.coordinateSystem.translate(Vector3d(iBottomCenter.x,iBottomCenter.y,iBottomCenter.z)) 173 return m
174 175 176 177
178 -def xCylinderFaceted(iInnerRadius, iOuterRadius, iBottomCenter, iHeight,iDivisions = 32):
179 """ 180 yCylinderFaceted(iInnerRadius, iOuterRadius, iBottomCenter, iHeight, iDivisions) 181 Creates a regular polygonal prism with primary axis along the x-axis. 182 @type iInnerRadius: float 183 @param iInnerRadius: inner radius of the cylinder 184 @type iOuterRadius: float 185 @param iOuterRadius: outer radius of the cylinder 186 @type iBottomCenter: L{Vector3d} 187 @param iBottomCenter: center of the bottom of the cylinder 188 @type iHeight: float 189 @param iHeight: height of the cylinder 190 @param iDivisions: the number of divisions to use for the cylinder 191 @type iDivisions: int 192 @rtype: L{Part} 193 @return: the prism as L{Part} 194 """ 195 m = zCylinderFaceted(iInnerRadius, iOuterRadius, iBottomCenter, iHeight) 196 m.coordinateSystem.rotate(0.0,math.pi/2.0,0.0) 197 return m
198 199
200 -def yCylinderFaceted(iInnerRadius, iOuterRadius, iBottomCenter, iHeight,iDivisions = 32):
201 """ 202 yCylinderFaceted(iInnerRadius, iOuterRadius, iBottomCenter, iHeight, iDivisions) 203 Creates a regular polygonal prism with primary axis along the y-axis. 204 @type iInnerRadius: float 205 @param iInnerRadius: inner radius of the cylinder 206 @type iOuterRadius: float 207 @param iOuterRadius: outer radius of the cylinder 208 @type iBottomCenter: L{Vector3d} 209 @param iBottomCenter: center of the bottom of the cylinder 210 @type iHeight: float 211 @param iHeight: height of the cylinder 212 @param iDivisions: the number of divisions to use for the cylinder 213 @type iDivisions: int 214 @rtype: L{Part} 215 @return: the prism as L{Part} 216 """ 217 m = zCylinderFaceted(iInnerRadius, iOuterRadius, iBottomCenter, iHeight) 218 m.coordinateSystem.rotate(math.pi/2.0,0.0,0.0) 219 return m
220 221
222 -def __regularPoly(iCenter, iRadius, iDivisions):
223 divisions = max(3,iDivisions) 224 iRadius = max(0.00000001,iRadius) 225 thetas = [i * 2 * math.pi / float(divisions) for i in range(iDivisions)] 226 return [Vector3d(iRadius * math.cos(theta), iRadius * math.sin(theta), 0) for theta in thetas]
227 228
229 -def __addPolyToSketch(iSketch, iPoints):
230 tails = iPoints 231 heads = iPoints[1:] + [iPoints[0]] 232 for tail, head in zip(tails, heads): 233 iSketch.add(Line(tail, head))
234 235
236 -def zCylinderFaceted(iInnerRadius, iOuterRadius, iBottomCenter, iHeight, iDivisions = 32):
237 """ 238 zCylinderFaceted(iInnerRadius, iOuterRadius, iBottomCenter, iHeight, iDivisions) 239 Creates a regular polygonal prism with primary axis along the z-axis. 240 @type iInnerRadius: float 241 @param iInnerRadius: inner radius of the cylinder 242 @type iOuterRadius: float 243 @param iOuterRadius: outer radius of the cylinder 244 @type iBottomCenter: L{Vector3d} 245 @param iBottomCenter: center of the bottom of the cylinder 246 @type iHeight: float 247 @param iHeight: height of the cylinder 248 @param iDivisions: the number of divisions to use for the cylinder 249 @type iDivisions: int 250 @rtype: L{Part} 251 @return: the prism as L{Part} 252 """ 253 import empro 254 m = Model() 255 m.recipe = Recipe() 256 orValue = float(empro.core.Expression(iOuterRadius)) 257 irValue = float(empro.core.Expression(iInnerRadius)) 258 idivValue = int(empro.core.Expression(iDivisions)) 259 if irValue > 0.0 : 260 s = Sketch() # during extrusion the Sketch is used as _relative_ geometry 261 bottomCenter = Vector3d(0.0,0.0,0.0) 262 __addPolyToSketch(s, __regularPoly( bottomCenter, orValue, idivValue)) 263 __addPolyToSketch(s, __regularPoly( bottomCenter, irValue, idivValue)) 264 iHeight = max(0.00000001,iHeight) 265 prism = Extrude(s,iHeight) 266 m.recipe.append( prism ) 267 else : # iInnerRadius == 0 -> use primitive components (prism) 268 libcmpnt = empro.geometry.Prism( iHeight, iOuterRadius, iOuterRadius, iDivisions) 269 m.recipe.append(libcmpnt) 270 angle = math.pi/idivValue 271 m.coordinateSystem.rotate(0.0,0.0,angle) # the acis component was rotated compared to the __addPolyToSketch 272 m.coordinateSystem.translate(Vector3d(iBottomCenter.x,iBottomCenter.y,iBottomCenter.z)) 273 return m
274 275
276 -def xRegularPolygonalPrism(iBottomCenter, iRadius, iHeight, iDivisions = 32):
277 """ 278 xRegularPolygonalPrism(iBottomCenter, iRadius, iHeight, iDivisions) 279 Creates a regular polygonal prism with primary axis along the X-axis. 280 @type iBottomCenter: L{Vector3d} 281 @param iBottomCenter: the center of the bottom of the prism 282 @type iRadius: float 283 @param iRadius: the radius where the vertices of the regular polygon are placed 284 @type iHeight: float 285 @param iHeight: the height of the prism 286 @param iDivisions: the number of divisions to use for the prism 287 @type iDivisions: int 288 @rtype: L{Part} 289 @return: the prism as L{Part} 290 """ 291 m = zRegularPolygonalPrism(iBottomCenter, iRadius, iHeight, iDivisions) 292 m.coordinateSystem.rotate(0.0,math.pi/2.0,0.0) 293 return m
294
295 -def yRegularPolygonalPrism(iBottomCenter, iRadius, iHeight, iDivisions = 32):
296 """ 297 yRegularPolygonalPrism(iBottomCenter, iRadius, iHeight, iDivisions) 298 Creates a regular polygonal prism with primary axis along the Y-axis. 299 @type iBottomCenter: L{Vector3d} 300 @param iBottomCenter: the center of the bottom of the prism 301 @type iRadius: float 302 @param iRadius: the radius where the vertices of the regular polygon are placed 303 @type iHeight: float 304 @param iHeight: the height of the prism 305 @param iDivisions: the number of divisions to use for the prism 306 @type iDivisions: int 307 @rtype: L{Part} 308 @return: the prism as L{Part} 309 """ 310 m = zRegularPolygonalPrism(iBottomCenter, iRadius, iHeight, iDivisions) 311 m.coordinateSystem.rotate(math.pi/2.0,0.0,0.0) 312 return m
313
314 -def zRegularPolygonalPrism(iBottomCenter, iRadius, iHeight, iDivisions = 32):
315 """ 316 zRegularPolygonalPrism(iBottomCenter, iRadius, iHeight, iDivisions) 317 Creates a regular polygonal prism with primary axis along the z-axis. 318 @type iBottomCenter: L{Vector3d} 319 @param iBottomCenter: the center of the bottom of the prism 320 @type iRadius: float 321 @param iRadius: the radius where the vertices of the regular polygon are placed 322 @type iHeight: float 323 @param iHeight: the height of the prism 324 @param iDivisions: the number of divisions to use for the prism 325 @type iDivisions: int 326 @rtype: L{Part} 327 @return: the prism as L{Part} 328 """ 329 import empro 330 libcmpnt = empro.geometry.Prism( iHeight, iRadius, iRadius, iDivisions) 331 m = Model() 332 m.recipe = Recipe() 333 m.recipe.append(libcmpnt) 334 idivValue = int(empro.core.Expression(iDivisions)) 335 angle = math.pi/idivValue 336 m.coordinateSystem.rotate(0.0,0.0,angle) # the acis component was rotated compared to the PolySketch 337 m.coordinateSystem.translate(Vector3d(iBottomCenter.x,iBottomCenter.y,iBottomCenter.z)) 338 return m
339 340 # 2D primitives
341 -def plateXY(iCenter, iDeltaX, iDeltaY, iName = "PlateXY"):
342 """ 343 plateXY(iCenter, iDeltaX, iDeltaY) 344 plateXY(iCenter, iDeltaX, iDeltaY, iName) 345 Returns a rectangular plate parallel to the XY-plane. 346 @type iCenter: L{Vector3d} 347 @param iCenter: the center of the plate 348 @type iDeltaX: float 349 @param iDeltaX: the width of the plate along the X-axis 350 @type iDeltaY: float 351 @param iDeltaY: the width of the plate along the Y-axis 352 @type iName: string 353 @param iName: the name of the plate (Default = "PlateXY") 354 @rtype: L{Part} 355 @return: the plate as L{Part} 356 """ 357 V = Vector3d 358 p1 = iCenter + V(-iDeltaX/2.0,-iDeltaY/2,0.0) 359 p2 = iCenter + V(-iDeltaX/2.0,iDeltaY/2,0.0) 360 p3 = iCenter + V(iDeltaX/2.0,iDeltaY/2,0.0) 361 p4 = iCenter + V(iDeltaX/2.0,-iDeltaY/2,0.0) 362 return PolyPlate([p1, p2, p3, p4], iName)
363 364
365 -def plateZX(iCenter, iDeltaZ, iDeltaX, iName = "PlateZX"):
366 """ 367 plateZX(iCenter, iDeltaZ, iDeltaX) 368 plateZX(iCenter, iDeltaZ, iDeltaX, iName) 369 Returns a rectangular plate parallel to the ZX-plane. 370 @type iCenter: L{Vector3d} 371 @param iCenter: the center of the plate 372 @type iDeltaZ: float 373 @param iDeltaZ: the width of the plate along the Z-axis 374 @type iDeltaX: float 375 @param iDeltaX: the width of the plate along the X-axis 376 @type iName: string 377 @param iName: the name of the plate (Default = "PlateZX") 378 @rtype: L{Part} 379 @return: the plate as L{Part} 380 """ 381 382 V = Vector3d 383 p1 = iCenter + V(-iDeltaX/2.0,0.0,-iDeltaZ/2) 384 p2 = iCenter + V(-iDeltaX/2.0,0.0,iDeltaZ/2) 385 p3 = iCenter + V(iDeltaX/2.0,0.0,iDeltaZ/2) 386 p4 = iCenter + V(iDeltaX/2.0,0.0,-iDeltaZ/2) 387 return PolyPlate([p1, p2, p3, p4], iName)
388
389 -def plateYZ(iCenter, iDeltaY, iDeltaZ, iName = "PlateYZ"):
390 """ 391 plateYZ(iCenter, iDeltaY, iDeltaZ) 392 plateYZ(iCenter, iDeltaY, iDeltaZ, iName) 393 Returns a rectangular plate parallel to the YZ-plane. 394 @type iCenter: L{Vector3d} 395 @param iCenter: the center of the plate 396 @type iDeltaY: float 397 @param iDeltaY: the width of the plate along the Y-axis 398 @type iDeltaZ: float 399 @param iDeltaZ: the width of the plate along the Z-axis 400 @type iName: string 401 @param iName: the name of the plate (Default = "PlateYZ") 402 @rtype: L{Part} 403 @return: the plate as L{Part} 404 """ 405 406 V = Vector3d 407 p1 = iCenter + V(0.0,-iDeltaY/2.0,-iDeltaZ/2) 408 p2 = iCenter + V(0.0,-iDeltaY/2.0,iDeltaZ/2) 409 p3 = iCenter + V(0.0,iDeltaY/2.0,iDeltaZ/2) 410 p4 = iCenter + V(0.0,iDeltaY/2.0,-iDeltaZ/2) 411 return PolyPlate([p1, p2, p3, p4], iName)
412 413
414 -def zCircle(iCenter,iRadius):
415 """ 416 zCircle(iCenter,iRadius) 417 Returns a circle parallel to the XY-plane. 418 @type iCenter: L{Vector3d} 419 @param iCenter: the center of the circle 420 @type iRadius: float 421 @param iRadius: the radius of the circle 422 @rtype: L{Part} 423 @return: the circle as L{Part} 424 """ 425 return Ellipse( iCenter, Vector3d(iRadius,0,iCenter.z), 1.0, 0.0, 2.0*math.pi )
426
427 -def QuadPlate(iPoint1, iPoint2, iPoint3, iPoint4, iName="QuadPlate"):
428 """ 429 QuadPlate(iPoint1,iPoint2,iPoint3,iPoint4) 430 QuadPlate(iPoint1,iPoint2,iPoint3,iPoint4,iName) 431 Returns a plate defined by four points. 432 @type iPoint1: L{Vector3d} 433 @param iPoint1: the first point of the plate 434 @type iPoint2: L{Vector3d} 435 @param iPoint2: the second point of the plate 436 @type iPoint3: L{Vector3d} 437 @param iPoint3: the third point of the plate 438 @type iPoint4: L{Vector3d} 439 @param iPoint4: the fourth point of the plate 440 @type iName: string 441 @param iName: the name of the plate (Default = "QuadPlate") 442 @rtype: L{Part} 443 @return: the plate as L{Part} 444 """ 445 return PolyPlate([iPoint1, iPoint2, iPoint3, iPoint4], iName)
446
447 -def PolyPlate(iPoints, iName="PolyPlate"):
448 """ 449 PolyPlate([iPoint1, iPoint2, ...]) 450 PolyPlate([iPoint1, iPoint2, ...], iName) 451 Returns a plate defined by a polygon 452 @type iPoints: list<L{Vector3d}> 453 @param iPoints: a sequence of polygon vertices. 454 @type iName: string 455 @param iName: the name of the plate (Default = "PolyPlate") 456 @rtype: L{Part} 457 @return: the plate as L{Part} 458 """ 459 import empro 460 tails = iPoints 461 heads = iPoints[1:] + [iPoints[0]] 462 edges = [] 463 for tail, head in zip(tails, heads): 464 edges.append( empro.acis.EDGE.curveLine( _toTuple(tail), _toTuple(head) )) 465 body, wires = empro.acis._coverPlanarEdges(edges,0) 466 m = empro.geometry.Model() 467 m.recipe.append( empro.geometry.ImportedCadEntity( body ) ) 468 m.name = iName 469 return m
470
471 -def _toTuple( c ):
472 import empro 473 unit = empro.activeProject.displayUnits["LENGTH"] 474 return (unit.fromReferenceUnits(float(c.x)), unit.fromReferenceUnits(float(c.y)), unit.fromReferenceUnits(float(c.z)))
475
476 -def PolySketch(iPoints, iName="PolySketch"):
477 """ 478 PolySketch([iPoint1, iPoint2, ...]) 479 PolySketch([iPoint1, iPoint2, ...], iName) 480 Returns a sketch defined by a polygon 481 @type iPoints: list<L{Vector3d}> 482 @param iPoints: a sequence of polygon vertices. 483 @type iName: string 484 @param iName: the name of the sketch (Default = "PolySketch") 485 @rtype: L{Sketch} 486 @return: polygonal sketch 487 """ 488 sketch = Sketch() 489 sketch.name = iName 490 __addPolyToSketch(sketch, iPoints) 491 return sketch
492 493 # 2D to 3D
494 -def sheetBody(iSketch, iName = None):
495 iName = iName or iSketch.name 496 m = Model() 497 m.name = iName 498 m.recipe = Recipe() 499 m.recipe.name = iName 500 c = Cover(iSketch) 501 c.name = iName 502 m.recipe.append(c) 503 return m
504 505 # 2D to 3D
506 -def extrude(iSketch,iDistance):
507 extrusion = Extrude(iSketch,iDistance) 508 m = Model() 509 m.recipe = Recipe() 510 m.recipe.append(extrusion) 511 return m
512 513 # serialization
514 -def base64SAT(iDObject):
515 import empro 516 desc3d = "" 517 (tf,tfn) = tempfile.mkstemp() 518 prevUnit = iDObject.unit 519 iObject = iDObject.clone() 520 __matchCoordinateSystems(iDObject,iObject) 521 canonicalUnit(iObject) 522 iObject.unit = empro.units.unitByAbbreviation("m") 523 iObject.exportToSAT(tfn) 524 iObject.unit = prevUnit 525 # now read back in the file and encode 526 f = open(tfn,"r") 527 text = "".join(f.readlines()) 528 f.close() 529 return base64.b64encode(text)
530
531 -def base64faceSAT(iDObject,iFace):
532 import empro 533 desc3d = "" 534 (tf,tfn) = tempfile.mkstemp() 535 prevUnit = iDObject.unit 536 iObject = iDObject.clone() 537 __matchCoordinateSystems(iDObject,iObject) 538 canonicalUnit(iObject) 539 iObject.unit = empro.units.unitByAbbreviation("m") 540 iObject.exportFaceToSAT(iFace,tfn) 541 iObject.unit = prevUnit 542 # now read back in the file and encode 543 f = open(tfn,"r") 544 text = "".join(f.readlines()) 545 f.close() 546 return base64.b64encode(text)
547 548 # returns a not-necessarily unique list of materials used by an object iObject
549 -def __materialsUsedBy(iObject,iFilter):
550 temp = [] 551 if isinstance(iObject,Assembly): 552 for i in range(len(iObject)): 553 if iFilter: 554 if iFilter(iObject[i]): 555 temp += materialsUsedBy(iObject[i]) 556 else: 557 temp += materialsUsedBy(iObject[i]) 558 else: 559 temp.append(iObject.material) 560 return temp
561 562 # returns a unique list of materials used by an object iObject
563 -def materialsUsedBy(iObject,iFilter=None):
564 temp = __materialsUsedBy(iObject,iFilter) 565 r = [] 566 tempSet = set() 567 for m in temp: 568 if m!=None: 569 if not m.hash() in tempSet: 570 r.append(m) 571 tempSet.add(m.hash()) 572 return r
573 574
575 -def __sliceXY(iObject,zHeight,iSlices):
576 if isinstance(iObject,Assembly): 577 for i in range(len(iObject)): 578 __sliceXY(iObject[i],zHeight,iSlices) 579 return 580 bb = iObject.boundingBox() 581 xExtent = float(bb.extent().x)*1.1 582 yExtent = float(bb.extent().y)*1.1 583 cutplane = plateXY(Vector3d(bb.center().x,bb.center().y,zHeight), xExtent, yExtent) 584 slice = Boolean.intersect(cutplane,iObject) 585 if abs(float(slice.boundingBox().extent().z))<0.01: # ACIS sometimes gives thick intersection for some reason 586 iSlices.append(slice)
587
588 -def sliceXY(iObject,zHeight):
589 """ 590 sliceXY(iObject, zHeight) 591 Computes a slice of iObject at height zHeight. 592 @type iObject: L{Part} 593 @param iObject: a part that can be an L{Assembly} that needs to be sliced 594 @type zHeight: float 595 @param zHeight: the height at which the slice is to be taken 596 @rtype: L{Part} 597 @return: the slice as L{Part} 598 """ 599 slices = [] 600 if isinstance(iObject,Assembly): 601 for i in range(len(iObject)): 602 __sliceXY(iObject[i],zHeight,slices) 603 else: 604 __sliceXY(iObject,zHeight,slices) 605 if len(slices)==0: 606 return None 607 if len(slices)==1: 608 return slices[0] 609 assemb = Assembly() 610 for s in slices: 611 assemb.append(s) 612 return assemb
613
614 -def __absoluteFacets(iPart):
615 usc = iPart.unit.toReferenceUnits(1.0) 616 newAbsFacets = [] 617 rawFacets = iPart.facetFaces() 618 for (facetName, facets) in rawFacets: 619 newFacets = [] 620 for facet in facets: 621 def vec(x): 622 return Vector3d(usc*x[0],usc*x[1],usc*x[2])
623 newFacet = [iPart.coordinateSystem.transformPosition(vec(facet[t]),"LocalToGlobal") for t in [0,1,2]] 624 newFacets.append(newFacet) 625 newAbsFacets.append( (facetName, newFacets) ) 626 return newAbsFacets 627
628 -def absoluteFacets(iObject):
629 """ 630 absoluteFacets. Only for internal usage. 631 """ 632 totalSetOfFacets = [] 633 if isinstance(iObject,Assembly): 634 for i in range(len(iObject)): 635 totalSetOfFacets += __absoluteFacets(iObject[i]) 636 else: 637 totalSetOfFacets = __absoluteFacets(iObject) 638 return totalSetOfFacets
639 640
641 -def assemblyFlatListInOrder(iAss):
642 """ 643 assemblyFlatListInOrder(iAssembly) 644 Returns a flat list of all parts (excluding assemblies) in order as they appear in the project tree. 645 @type iObject: L{Part} 646 @param iObject: a part that can be an L{Assembly} that needs to be flat listed 647 @rtype: list<L{Part}> 648 @return: the ordered list of L{Part}'s 649 """ 650 ret = [] 651 if issubclass(type(iAss),Assembly): 652 for i in range(len(iAss)): 653 ret += assemblyFlatListInOrder(iAss[i]) 654 elif issubclass(type(iAss), OaLayout): 655 ret += assemblyFlatListInOrder(iAss._assembly) 656 else: 657 ret = [iAss] 658 return ret
659
660 -def removeThinShelling(iObject, iThicknessThreshold):
661 """ 662 removeThinShelling(iObject) 663 Removes all thin shelling on an object. 664 @type iObject: L{Part} 665 @param iObject: a part that needs to be handled 666 @type iThicknessThreshold: float 667 @param iThicknessThreshold: all shells below this value will be removed 668 @rtype: None 669 @return: None 670 """ 671 import empro 672 if type(iObject)==empro.geometry.Model: 673 recipe = iObject.recipe 674 for feature in range(len(recipe)): 675 if not recipe[feature].isSuppressed() and type(recipe[feature])==empro.geometry.Shell: 676 thickness = recipe[feature].thickness 677 if (thickness<iThicknessThreshold): 678 faces = recipe[feature].openFaces 679 newFeature = empro.geometry.RemoveFaces(faces) 680 recipe[feature].suppress() 681 recipe.append(newFeature) 682 if not recipe[feature].isSuppressed() and type(recipe[feature])==empro.geometry.BooleanOperation: 683 removeThinShelling(recipe[feature].tool(),iThicknessThreshold) 684 removeThinShelling(recipe[feature].blank(),iThicknessThreshold)
685 686
687 -def shellThicknesses(iObject):
688 """ 689 removeThinShelling(iObject) 690 Removes all thin shelling on an object. 691 @type iObject: L{Part} 692 @param iObject: a part that needs to be handled 693 @type iThicknessThreshold: float 694 @param iThicknessThreshold: all shells below this value will be removed 695 @rtype: None 696 @return: None 697 """ 698 import empro 699 thicknesses = [] 700 if type(iObject)==empro.geometry.Model: 701 recipe = iObject.recipe 702 for feature in range(len(recipe)): 703 if not recipe[feature].isSuppressed() and type(recipe[feature])==empro.geometry.Shell: 704 thicknesses.append(float(recipe[feature].thickness)) 705 if not recipe[feature].isSuppressed() and type(recipe[feature])==empro.geometry.BooleanOperation: 706 thicknesses += shellThicknesses(recipe[feature].tool()) 707 thicknesses += shellThicknesses(recipe[feature].blank()) 708 return thicknesses
709