2 This page is in the table of contents.
3 The gear script can generate a spur gear couple, a bevel gear couple, a ring gear couple and a rack & pinion couple.
5 A helix pattern can be added to each gear type. All the gear types have a clearance and all the teeth can be beveled. A keyway, shaft and lightening holes can be added to all the round gears, and rack holes can be added to the rack. The script can output solid gears or only the gear profiles. Both gears of the couple can be generated or just one.
7 The couple has a pinion gear and a complement.
10 The link text includes the distinguishing parameters. Each svg page was generated from an xml page of the same root name using carve. For example, gear.svg was generated by clicking 'Carve' on the carve tool panel and choosing gear.xml in the file chooser.
12 Each generated svg file has the xml fabmetheus element without comments towards the end of the file. To see it, open the svg file in a text editor and search for 'fabmetheus' If you copy that into a new text document, add the line '<?xml version='1.0' ?>' at the beginning and then give it a file name with the extension '.xml', you could then generate another svg file using carve.
17 <a href='../models/xml_models/creation/gear/bevel.svg'>gear operatingAngle=90</a>
20 Spur gear couple and each gear has a collar.
22 <a href='../models/xml_models/creation/gear/collar.svg'>gear complementCollarLengthOverFaceWidth='1' pinionCollarLengthOverFaceWidth='1' shaftRadius='5'</a>
25 Default spur gear with no parameters.
27 <a href='../models/xml_models/creation/gear/gear.svg'>gear</a>
30 Spur gear couple and each gear has a collar and defined keyway.
32 <a href='../models/xml_models/creation/gear/keyway.svg'>gear complementCollarLengthOverFaceWidth='1' keywayRadius='2' pinionCollarLengthOverFaceWidth='1' shaftRadius='5'</a>
35 Rack and pinion couple.
37 <a href='../models/xml_models/creation/gear/rack.svg'>gear teethComplement='0'</a>
40 Rack and pinion couple, with holes in the rack.
42 <a href='../models/xml_models/creation/gear/rack_hole.svg'>gear rackHoleRadiusOverWidth='0.2' rackWidthOverFaceWidth='2' teethComplement='0'</a>
47 <a href='../models/xml_models/creation/gear/ring.svg'>gear teethComplement='-23'</a>
50 Spur gear couple and each gear has a square shaft hole.
52 <a href='../models/xml_models/creation/gear/shaft.svg'>gear shaftRadius='5'</a>
55 Spur gear couple and each gear has a round shaft hole, truncated on top.
57 <a href='../models/xml_models/creation/gear/shaft_top.svg'>gear shaftRadius='5' shaftSides='13' shaftDepthTop='2'</a>
60 Spur gear couple with the gear teeth following a helix path.
62 <a href='../models/xml_models/creation/gear/spur_helix.svg'>gear helixAngle='45'</a>
64 ===Spur Herringbone===
65 Spur gear couple with the gear teeth following a herringbone path.
67 <a href='../models/xml_models/creation/gear/spur_herringbone.svg'>gear helixAngle='45' helixType='herringbone'</a>
70 Spur gear couple with the gear teeth following a parabolic path.
72 <a href='../models/xml_models/creation/gear/spur_parabolic.svg'>gear helixAngle='45' helixType='parabolic'</a>
75 Spur gear couple profile. Since this is just a horizontal path, it can not be sliced, so the path is then extruded to create a solid which can be sliced and viewed.
77 <a href='../models/xml_models/creation/gear/spur_profile.svg'>gear id='spurProfile' faceWidth='0' | extrude target='=document.getElementByID(spurProfile)</a>
81 Default is such that the pitch radius works out to twenty.
83 Defines the distance between the gear centers.
85 ===Clearance Couplet===
86 ====Clearance Over Wavelength====
89 Defines the ratio of the clearance over the wavelength of the gear profile. The wavelength is the arc distance between the gear teeth.
92 Default is the 'Clearance Over Wavelength' times the wavelength.
94 Defines the clearance between the gear tooth and the other gear of the couple. If the clearance is zero, the outside of the gear tooth will touch the other gear. If the clearance is too high, the gear teeth will be long and weak.
96 ===Collar Addendum Couplet===
97 ====Collar Addendum Over Radius====
100 Defines the ratio of the collar addendum over the shaft radius.
102 ====Collar Addendum====
103 Default is the 'Collar Addendum Over Radius' times the shaft radius.
105 Defines the collar addendum.
107 ===Complement Collar Length Couplet===
108 ====Complement Collar Length Over Face Width====
111 Defines the ratio of the complement collar length over the face width.
113 ====Complement Collar Length====
114 Default is the 'Complement Collar Length Over Face Width' times the face width.
116 Defines the complement collar length. If the complement collar length is zero, there will not be a collar on the complement gear.
122 When selected, the pinion and complement will be generated.
125 When selected, only the complement gear or rack will be generated.
128 When selected, only the pinion will be generated.
133 Defines the face width.
135 ===Gear Hole Paths===
138 Defines the centers of the gear holes. If the gear hole paths parameter is the default empty, then the centers of the gear holes will be generated from other parameters.
146 Defines the helix path of the gear teeth. If the helix path is the default empty, then the helix will be generated from the helix angle and helix type.
152 When selected, the helix will be basic.
155 When selected, the helix will have a herringbone pattern.
158 When selected, the helix will have a parabolic pattern.
160 ===Keyway Radius Couplet===
161 ====Keyway Radius Over Radius====
164 Defines the ratio of the keyway radius over the shaft radius.
166 ====Keyway Radius====
167 Default is the 'Keyway Radius Over Radius' times the shaft radius.
169 Defines the keyway radius. If the keyway radius is zero, there will not be a keyway on the collar.
171 ===Lightening Hole Margin Couplet===
172 ====Lightening Hole Margin Over Rim Dedendum====
175 Defines the ratio of the lightening hole margin over the rim dedendum.
177 ====Lightening Hole Margin====
178 Default is the 'Lightening Hole Margin Over Rim Dedendum' times the rim dedendum.
180 Defines the minimum margin between lightening holes.
182 ===Lightening Hole Minimum Radius===
185 Defines the minimum radius of the lightening holes.
188 Default is 'separate'.
191 When selected, the gears will be not be moved and will therefore overlap. Afterwards the write plugin could be used to write each gear to a different file, so they can be fabricated in separate operations.
194 When selected, the gears will be separated horizontally so that they just mesh. This is useful to test if the gears mesh properly.
197 When selected, the gears will be separated horizontally with a gap between them.
200 When selected, the gears will be separated vertically.
202 ===Operating Angle===
203 Default is 180 degrees.
205 Defines the operating angle between the gear axes. If the operating angle is not 180 degrees, a bevel gear couple will be generated.
207 ===Pinion Collar Length Couplet===
208 ====Pinion Collar Length Over Face Width====
211 Defines the ratio of the pinion collar length over the face width.
213 ====Pinion Collar Length====
214 Default is the 'Pinion Collar Length Over Face Width' times the face width.
216 Defines the pinion collar length. If the pinion collar length is zero, there will not be a collar on the pinion gear.
219 Default is twenty if the pitch radius has not been set. If the center distance is set, the default pitch radius is the center distance times the number of pinion teeth divided by the total number of gear teeth.
221 Defines the pinion pitch radius.
223 ===Plate Clearance Couplet===
224 ====Plate Clearance Over Length====
227 Defines the ratio of the plate clearance over the plate length.
229 ====Plate Clearance====
230 Default is the 'Plate Clearance Over Length' times the plate length.
232 Defines the clearance between the pinion and the plate of the ring gear. If the clearance is zero, they will touch.
234 ===Plate Length Couplet===
235 ====Plate Length Over Face Width====
238 Defines the ratio of the plate length over the face width.
241 Default is the 'Plate Length Over Face Width' times the face width.
243 Defines the length of the plate of the ring gear.
246 Default is twenty degrees.
248 Defines the pressure angle of the gear couple.
250 ===Profile Surfaces===
253 Defines the number of profile surfaces.
255 ===Rack Hole Below Over Width Couplet===
256 ====Rack Hole Below Over Width====
259 Defines the ratio of the distance below the pitch of the rack holes over the rack width.
261 ====Rack Hole Below====
262 Default is the 'Rack Hole Below Over Width' times the rack width.
264 Defines the the distance below the pitch of the rack holes.
266 ===Rack Hole Radius Couplet===
267 ====Rack Hole Radius Over Width====
270 Defines the ratio of the rack hole radius over the rack width.
272 ====Rack Hole Radius====
273 Default is the 'Rack Hole Radius Over Width' times the rack width.
275 Defines the radius of the rack holes. If the rack hole radius is zero, there won't be any rack holes.
277 ===Rack Hole Step Over Width Couplet===
278 ====Rack Hole Step Over Width====
281 Defines the ratio of the rack hole step over the rack width.
283 ====Rack Hole Step====
284 Default is the 'Rack Hole Step Over Width' times the rack width.
286 Defines the horizontal step distance between the rack holes.
288 ===Rack Length Over Radius Couplet===
289 ====Rack Length Over Radius====
290 Default is two times pi.
292 Defines the ratio of the rack length over the pitch radius.
295 Default is the 'Rack Length Over Radius' times the pitch radius.
297 Defines the rack length.
299 ===Rack Width Couplet===
300 ====Rack Width Over Face Width====
303 Defines the ratio of the rack width over the face width.
306 Default is the 'Rack Width Over Face Width' times the face width.
308 Defines the rack width.
310 ===Rim Dedendum Couplet===
311 ====Rim Dedendum Over Radius====
314 Defines the ratio of the rim dedendum over the pitch radius.
317 Default is the 'Rim Dedendum Over Radius' times the pitch radius.
319 Defines the rim dedendum of the gear.
321 ===Root Bevel Couplet===
322 ====Root Bevel Over Clearance====
325 Defines the ratio of the root bevel over the clearance.
328 Default is the 'Root Bevel Over Clearance' times the clearance.
330 Defines the bevel at the root of the gear tooth.
332 ===Shaft Depth Bottom Couplet===
333 ====Shaft Depth Bottom Over Radius====
336 Defines the ratio of the bottom shaft depth over the shaft radius.
338 ====Shaft Depth Bottom====
339 Default is the 'Shaft Depth Bottom Over Radius' times the shaft radius.
341 Defines the bottom shaft depth.
343 ===Shaft Depth Top Couplet===
344 ====Shaft Depth Top Over Radius====
347 Defines the ratio of the top shaft depth over the shaft radius.
349 ====Shaft Depth Top====
350 Default is the 'Shaft Depth Top Over Radius' times the shaft radius.
352 Defines the top shaft depth.
357 Defines the path of the shaft hole. If the shaft path is the default empty, then the shaft path will be generated from the shaft depth bottom, shaft depth top, shaft radius and shaft sides.
359 ===Shaft Radius Couplet===
360 ====Shaft Radius Over Pitch Radius====
363 Defines the ratio of the shaft radius over the pitch radius.
366 Default is the 'Shaft Radius Over Pitch Radius' times the pitch radius.
368 Defines the shaft radius. If the shaft radius is zero there will not be a shaft hole.
373 Defines the number of shaft sides.
378 Defines the number of teeth in the pinion.
380 ===Teeth Complement===
381 Default is seventeen.
383 Defines the number of teeth in the complement of the gear couple. If the number of teeth is positive, the gear couple will be a spur or bevel type. If the number of teeth is zero, the gear couple will be a rack and pinion. If the number of teeth is negative, the gear couple will be a spur and ring.
385 ===Tip Bevel Couplet===
386 ====Tip Bevel Over Clearance====
389 Defines the ratio of the tip bevel over the clearance.
392 Default is the 'Tip Bevel Over Clearance' times the clearance.
394 Defines the bevel at the tip of the gear tooth.
396 ===Tooth Thickness Multiplier===
399 Defines the amount the thickness of the tooth will multiplied. If when the gears are produced, they mesh too tightly, you can reduce the tooth thickness multiplier so that they mesh with reasonable tightness.
403 from __future__ import absolute_import
404 #Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module.
407 from fabmetheus_utilities.geometry.creation import extrude
408 from fabmetheus_utilities.geometry.creation import lineation
409 from fabmetheus_utilities.geometry.creation import shaft
410 from fabmetheus_utilities.geometry.creation import solid
411 from fabmetheus_utilities.geometry.creation import teardrop
412 from fabmetheus_utilities.geometry.geometry_tools import path
413 from fabmetheus_utilities.geometry.geometry_utilities.evaluate_elements import setting
414 from fabmetheus_utilities.geometry.geometry_utilities import evaluate
415 from fabmetheus_utilities.geometry.geometry_utilities import matrix
416 from fabmetheus_utilities.geometry.solids import triangle_mesh
417 from fabmetheus_utilities.vector3 import Vector3
418 from fabmetheus_utilities.vector3index import Vector3Index
419 from fabmetheus_utilities import euclidean
423 __author__ = 'Enrique Perez (perez_enrique@yahoo.com)'
424 __credits__ = 'Art of Illusion <http://www.artofillusion.org/>'
425 __date__ = '$Date: 2008/02/05 $'
426 __license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
429 def addBevelGear(derivation, extrudeDerivation, pitchRadius, positives, teeth, vector3GearProfile):
430 "Get extrude output for a cylinder gear."
431 totalPitchRadius = derivation.pitchRadiusComplement + derivation.pitchRadius
432 totalTeeth = derivation.teethPinion + derivation.teethComplement
433 portionDirections = extrude.getSpacedPortionDirections(extrudeDerivation.interpolationDictionary)
434 loopLists = extrude.getLoopListsByPath(extrudeDerivation, None, vector3GearProfile[0], portionDirections)
435 firstLoopList = loopLists[0]
436 gearOverPinion = float(totalTeeth - teeth) / float(teeth)
437 thirdLayerHeight = 0.33333333333 * setting.getLayerHeight(derivation.elementNode)
438 pitchRadian = math.atan(math.sin(derivation.operatingRadian) / (gearOverPinion + math.cos(derivation.operatingRadian)))
439 coneDistance = pitchRadius / math.sin(pitchRadian)
440 apex = Vector3(0.0, 0.0, math.sqrt(coneDistance * coneDistance - pitchRadius * pitchRadius))
441 cosPitch = apex.z / coneDistance
442 sinPitch = math.sin(pitchRadian)
443 for loop in firstLoopList:
445 alongWay = point.z / coneDistance
446 oneMinusAlongWay = 1.0 - alongWay
447 pointComplex = point.dropAxis()
448 pointComplexLength = abs(pointComplex)
449 deltaRadius = pointComplexLength - pitchRadius
450 cosDeltaRadius = cosPitch * deltaRadius
451 sinDeltaRadius = sinPitch * deltaRadius
452 pointComplex *= (cosDeltaRadius + pitchRadius) / pointComplexLength
453 point.x = pointComplex.real
454 point.y = pointComplex.imag
455 point.z += sinDeltaRadius
456 point.x *= oneMinusAlongWay
457 point.y *= oneMinusAlongWay
458 addBottomLoop(-thirdLayerHeight, firstLoopList)
459 topLoop = firstLoopList[-1]
461 topZ = euclidean.getTopPath(topLoop) + thirdLayerHeight
462 oldIndex = topLoop[-1].index
463 for point in topLoop:
465 topAddition.append(Vector3Index(oldIndex, 0.8 * point.x, 0.8 * point.y, topZ))
466 firstLoopList.append(topAddition)
467 translation = Vector3(0.0, 0.0, -euclidean.getBottomByPaths(firstLoopList))
468 euclidean.translateVector3Paths(firstLoopList, translation)
469 geometryOutput = triangle_mesh.getPillarsOutput(loopLists)
470 positives.append(geometryOutput)
472 def addBottomLoop(deltaZ, loops):
473 "Add bottom loop to loops."
474 bottomLoop = loops[0]
476 bottomZ = euclidean.getBottomByPath(bottomLoop) + deltaZ
477 for point in bottomLoop:
478 bottomAddition.append(Vector3Index(len(bottomAddition), point.x, point.y, bottomZ))
479 loops.insert(0, bottomAddition)
483 point.index = numberOfVertexes
484 numberOfVertexes += 1
486 def addCollarShaft(collarLength, derivation, elementNode, negatives, positives):
488 if collarLength <= 0.0:
489 addShaft(derivation, negatives, positives)
491 connectionEnd = Vector3(0.0, 0.0, derivation.faceWidth + collarLength)
492 copyShallow = derivation.elementNode.getCopyShallow()
493 copyShallow.attributes['path'] = [Vector3(0.0, 0.0, derivation.faceWidth), connectionEnd]
494 collarDerivation = extrude.ExtrudeDerivation(copyShallow)
495 addCollarShaftSetDerivation(collarDerivation, collarLength, derivation, elementNode, negatives, positives)
497 def addCollarShaftSetDerivation(collarDerivation, collarLength, derivation, elementNode, negatives, positives):
498 'Add collar and shaft.'
499 collarSides = evaluate.getSidesMinimumThreeBasedOnPrecision(elementNode, derivation.shaftRimRadius)
500 collarProfile = euclidean.getComplexPolygon(complex(), derivation.shaftRimRadius, collarSides)
501 vector3CollarProfile = euclidean.getVector3Path(collarProfile)
502 extrude.addPositives(collarDerivation, [vector3CollarProfile], positives)
503 addShaft(derivation, negatives, positives)
504 drillZ = derivation.faceWidth + 0.5 * collarLength
505 drillEnd = Vector3(0.0, derivation.shaftRimRadius, drillZ)
506 drillStart = Vector3(0.0, 0.0, drillZ)
507 teardrop.addNegativesByRadius(elementNode, drillEnd, negatives, derivation.keywayRadius, drillStart)
509 def addLighteningHoles(derivation, gearHolePaths, negatives, pitchRadius, positives):
510 "Add lightening holes."
511 positiveVertexes = matrix.getVertexes(positives)
512 bottomPath = euclidean.getTopPath(positiveVertexes)
513 topPath = euclidean.getBottomByPath(positiveVertexes)
514 copyShallow = derivation.elementNode.getCopyShallow()
515 copyShallow.attributes['path'] = [Vector3(0.0, 0.0, bottomPath), Vector3(0.0, 0.0, topPath)]
516 extrudeDerivation = extrude.ExtrudeDerivation(copyShallow)
517 vector3LighteningHoles = getLighteningHoles(derivation, gearHolePaths, pitchRadius)
518 extrude.addNegativesPositives(extrudeDerivation, negatives, vector3LighteningHoles, positives)
520 def addRackHole(derivation, elementNode, vector3RackProfiles, x):
521 "Add rack hole to vector3RackProfiles."
522 rackHole = euclidean.getComplexPolygon(complex(x, -derivation.rackHoleBelow), derivation.rackHoleRadius, -13)
523 vector3RackProfiles.append(euclidean.getVector3Path(rackHole))
525 def addRackHoles(derivation, elementNode, vector3RackProfiles):
526 "Add rack holes to vector3RackProfiles."
527 if len(derivation.gearHolePaths) > 0:
528 vector3RackProfiles += derivation.gearHolePaths
530 if derivation.rackHoleRadius <= 0.0:
532 addRackHole(derivation, elementNode, vector3RackProfiles, 0.0)
533 rackHoleMargin = derivation.rackHoleRadius + derivation.rackHoleRadius
534 rackHoleSteps = int(math.ceil((derivation.rackDemilength - rackHoleMargin) / derivation.rackHoleStep))
535 for rackHoleIndex in xrange(1, rackHoleSteps):
536 x = float(rackHoleIndex) * derivation.rackHoleStep
537 addRackHole(derivation, elementNode, vector3RackProfiles, -x)
538 addRackHole(derivation, elementNode, vector3RackProfiles, x)
540 def addShaft(derivation, negatives, positives):
542 if len(derivation.shaftPath) < 3:
544 positiveVertexes = matrix.getVertexes(positives)
545 bottomPath = euclidean.getTopPath(positiveVertexes)
546 topPath = euclidean.getBottomByPath(positiveVertexes)
547 copyShallow = derivation.elementNode.getCopyShallow()
548 copyShallow.attributes['path'] = [Vector3(0.0, 0.0, bottomPath), Vector3(0.0, 0.0, topPath)]
549 extrudeDerivation = extrude.ExtrudeDerivation(copyShallow)
550 extrude.addNegativesPositives(extrudeDerivation, negatives, [derivation.shaftPath], positives)
552 def getAxialMargin(circleRadius, numberOfSides, polygonRadius):
554 return polygonRadius * math.sin(math.pi / float(numberOfSides)) - circleRadius
556 def getBevelPath(begin, bevel, center, end):
558 centerMinusBegin = center - begin
559 centerMinusBeginLength = abs(centerMinusBegin)
560 endMinusCenter = end - center
561 endMinusCenterLength = abs(endMinusCenter)
562 endMinusCenter /= endMinusCenterLength
563 maximumExtensionLength = 0.333333333 * endMinusCenterLength
564 if centerMinusBeginLength <= bevel * 1.5:
565 extensionLength = min(maximumExtensionLength, centerMinusBeginLength)
566 return [complex(center.real, center.imag) + extensionLength * endMinusCenter]
567 centerMinusBegin *= (centerMinusBeginLength - bevel) / centerMinusBeginLength
568 extensionLength = min(maximumExtensionLength, bevel)
569 bevelPath = [complex(center.real, center.imag) + extensionLength * endMinusCenter]
570 bevelPath.append(begin + centerMinusBegin)
573 def getGearPaths(derivation, pitchRadius, teeth, toothProfile):
576 return getGearProfileAnnulus(derivation, pitchRadius, teeth, toothProfile)
578 return [getGearProfileRack(derivation, toothProfile)]
579 return [getGearProfileCylinder(teeth, toothProfile)]
581 def getGearProfileAnnulus(derivation, pitchRadius, teeth, toothProfile):
582 'Get gear profile for an annulus gear.'
583 gearProfileCylinder = getGearProfileCylinder(teeth, toothProfile)
584 annulusRadius = derivation.dedendum + derivation.rimDedendum - pitchRadius
585 return [euclidean.getComplexPolygon(complex(), annulusRadius, -teeth, 0.5 * math.pi), gearProfileCylinder]
587 def getGearProfileCylinder(teeth, toothProfile):
588 'Get gear profile for a cylinder gear.'
590 toothAngleRadian = 2.0 * math.pi / float(teeth)
591 totalToothAngle = 0.0
592 for toothIndex in xrange(abs(teeth)):
593 for toothPoint in toothProfile:
594 gearProfile.append(toothPoint * euclidean.getWiddershinsUnitPolar(totalToothAngle))
595 totalToothAngle += toothAngleRadian
598 def getGearProfileRack(derivation, toothProfile):
599 'Get gear profile for rack.'
600 derivation.extraRackDemilength = 0.0
601 for complexPoint in derivation.helixPath:
602 derivation.extraRackDemilength = max(abs(derivation.helixHeight * complexPoint.imag), derivation.extraRackDemilength)
603 rackDemilengthPlus = derivation.rackDemilength
604 if derivation.faceWidth > 0.0:
605 derivation.extraRackDemilength *= 1.1
606 rackDemilengthPlus += derivation.extraRackDemilength
607 teethRack = int(math.ceil(rackDemilengthPlus / derivation.wavelength))
609 for toothIndex in xrange(-teethRack, teethRack + 1):
610 translateComplex = complex(-toothIndex * derivation.wavelength, 0.0)
611 translatedPath = euclidean.getTranslatedComplexPath(toothProfile, translateComplex)
612 gearProfile += translatedPath
613 gearProfile = euclidean.getHorizontallyBoundedPath(rackDemilengthPlus, -rackDemilengthPlus, gearProfile)
614 firstPoint = gearProfile[0]
615 lastPoint = gearProfile[-1]
616 rackWidth = derivation.rackWidth
617 minimumRackWidth = 1.1 * derivation.dedendum
618 if rackWidth < minimumRackWidth:
619 rackWidth = minimumRackWidth
620 print('Warning, rackWidth is too small in getGearProfileRack in gear.')
621 print('RackWidth will be set to a bit more than the dedendum.')
622 gearProfile += [complex(lastPoint.real, -rackWidth),complex(firstPoint.real, -rackWidth)]
625 def getGeometryOutput(derivation, elementNode):
626 "Get vector3 vertexes from attribute dictionary."
627 if derivation == None:
628 derivation = GearDerivation(elementNode)
629 creationFirst = derivation.creationType.lower()[: 1]
630 toothProfileComplement = getToothProfile(derivation, derivation.pitchRadiusComplement, derivation.teethComplement)
631 pinionProfile = getGearProfileCylinder(derivation.teethPinion, derivation.pinionToothProfile)
632 complementPaths = getGearPaths(
633 derivation, derivation.pitchRadiusComplement, derivation.teethComplement, toothProfileComplement)
634 vector3PinionProfile = euclidean.getVector3Path(pinionProfile)
635 vector3ComplementPaths = euclidean.getVector3Paths(complementPaths)
636 translation = Vector3()
637 moveFirst = derivation.moveType.lower()[: 1]
639 distance = derivation.pitchRadius
641 distance += derivation.pitchRadiusComplement
643 distance += abs(derivation.pitchRadiusComplement)
644 decimalPlaces = 1 - int(math.floor(math.log10(distance)))
645 distance += derivation.halfWavelength + derivation.halfWavelength
646 distance = round(1.15 * distance, decimalPlaces)
647 translation = Vector3(0.0, -distance)
648 if derivation.faceWidth <=0.0:
649 return getPathOutput(
650 creationFirst, derivation, elementNode, translation, vector3ComplementPaths, vector3PinionProfile)
651 pitchRadius = derivation.pitchRadius
652 teeth = derivation.teethPinion
653 twist = derivation.helixHeight / derivation.pitchRadius
654 extrudeOutputPinion = getOutputCylinder(
655 derivation.pinionCollarLength, derivation, elementNode, None, pitchRadius, teeth, twist, [vector3PinionProfile])
656 if creationFirst == 'p':
657 return extrudeOutputPinion
658 teeth = derivation.teethComplement
659 extrudeOutputSecond = None
661 extrudeOutputSecond = getOutputRack(derivation, elementNode, vector3ComplementPaths[0])
663 twist = -derivation.helixHeight / derivation.pitchRadiusComplement
664 extrudeOutputSecond = getOutputCylinder(
665 derivation.complementCollarLength,
668 derivation.gearHolePaths,
669 derivation.pitchRadiusComplement,
672 vector3ComplementPaths)
673 if creationFirst == 'c':
674 return extrudeOutputSecond
675 gearVertexes = matrix.getVertexes(extrudeOutputSecond)
677 translation = Vector3(0.0, 0.0, euclidean.getTopPath(gearVertexes))
678 euclidean.translateVector3Path(matrix.getVertexes(extrudeOutputPinion), translation)
680 euclidean.translateVector3Path(gearVertexes, translation)
681 return {'group' : {'shapes' : [extrudeOutputPinion, extrudeOutputSecond]}}
683 def getGeometryOutputByArguments(arguments, elementNode):
684 "Get vector3 vertexes from attribute dictionary by arguments."
685 return getGeometryOutput(None, elementNode)
687 def getHalfwave(pitchRadius, teeth):
688 'Get tooth halfwave.'
689 return pitchRadius * math.pi / float(teeth)
691 def getHelixComplexPath(derivation, elementNode):
692 'Set gear helix path.'
693 helixTypeFirstCharacter = derivation.helixType.lower()[: 1]
694 if helixTypeFirstCharacter == 'b':
695 return [complex(), complex(1.0, 1.0)]
696 if helixTypeFirstCharacter == 'h':
697 return [complex(), complex(0.5, 0.5), complex(1.0, 0.0)]
698 if helixTypeFirstCharacter == 'p':
699 helixComplexPath = []
701 xStep = setting.getLayerHeight(elementNode) / derivation.faceWidth
702 justBelowOne = 1.0 - 0.5 * xStep
703 while x < justBelowOne:
704 distanceFromCenter = 0.5 - x
705 parabolicTwist = 0.25 - distanceFromCenter * distanceFromCenter
706 helixComplexPath.append(complex(x, parabolicTwist))
708 helixComplexPath.append(complex(1.0, 0.0))
709 return helixComplexPath
710 print('Warning, the helix type was not one of (basic, herringbone or parabolic) in getHelixComplexPath in gear for:')
711 print(derivation.helixType)
712 print(derivation.elementNode)
714 def getLiftedOutput(derivation, geometryOutput):
715 "Get extrude output for a rack."
716 if derivation.moveType.lower()[: 1] == 'm':
717 return geometryOutput
718 geometryOutputVertexes = matrix.getVertexes(geometryOutput)
719 translation = Vector3(0.0, 0.0, -euclidean.getBottomByPath(geometryOutputVertexes))
720 euclidean.translateVector3Path(geometryOutputVertexes, translation)
721 return geometryOutput
723 def getLighteningHoles(derivation, gearHolePaths, pitchRadius):
724 'Get cutout circles.'
725 if gearHolePaths != None:
726 if len(gearHolePaths) > 0:
728 innerRadius = abs(pitchRadius) - derivation.dedendum
729 lighteningHoleOuterRadius = innerRadius - derivation.rimDedendum
730 shaftRimRadius = max(derivation.shaftRimRadius, (lighteningHoleOuterRadius) * (0.5 - math.sqrt(0.1875)))
731 lighteningHoleRadius = 0.5 * (lighteningHoleOuterRadius - derivation.shaftRimRadius)
732 if lighteningHoleRadius < derivation.lighteningHoleMinimumRadius:
735 numberOfLighteningHoles = 3
736 polygonRadius = lighteningHoleOuterRadius - lighteningHoleRadius
737 rimDemiwidth = 0.5 * derivation.lighteningHoleMargin
738 axialMargin = getAxialMargin(lighteningHoleRadius, numberOfLighteningHoles, polygonRadius)
739 if axialMargin < rimDemiwidth:
740 while axialMargin < rimDemiwidth:
741 lighteningHoleRadius *= 0.999
742 if lighteningHoleRadius < derivation.lighteningHoleMinimumRadius:
744 axialMargin = getAxialMargin(lighteningHoleRadius, numberOfLighteningHoles, polygonRadius)
746 newNumberOfLighteningHoles = numberOfLighteningHoles
747 while axialMargin > rimDemiwidth:
748 numberOfLighteningHoles = newNumberOfLighteningHoles
749 newNumberOfLighteningHoles += 2
750 axialMargin = getAxialMargin(lighteningHoleRadius, newNumberOfLighteningHoles, polygonRadius)
751 sideAngle = 2.0 * math.pi / float(numberOfLighteningHoles)
753 for lighteningHoleIndex in xrange(numberOfLighteningHoles):
754 unitPolar = euclidean.getWiddershinsUnitPolar(startAngle)
755 lighteningHole = euclidean.getComplexPolygon(unitPolar * polygonRadius, lighteningHoleRadius, -13)
756 lighteningHoles.append(lighteningHole)
757 startAngle += sideAngle
758 return euclidean.getVector3Paths(lighteningHoles)
760 def getNewDerivation(elementNode):
761 'Get new derivation.'
762 return GearDerivation(elementNode)
764 def getOutputCylinder(
765 collarLength, derivation, elementNode, gearHolePaths, pitchRadius, teeth, twist, vector3GearProfile):
766 "Get extrude output for a cylinder gear."
767 copyShallow = derivation.elementNode.getCopyShallow()
768 copyShallow.attributes['path'] = [Vector3(), Vector3(0.0, 0.0, derivation.faceWidth)]
769 extrudeDerivation = extrude.ExtrudeDerivation(copyShallow)
773 twistDegrees = math.degrees(twist)
774 extrudeDerivation.twistPathDefault = []
775 for complexPoint in derivation.helixPath:
776 extrudeDerivation.twistPathDefault.append(Vector3(complexPoint.real, twistDegrees * complexPoint.imag))
777 extrude.insertTwistPortions(extrudeDerivation, elementNode)
778 if derivation.operatingAngle != 180.0:
779 addBevelGear(derivation, extrudeDerivation, pitchRadius, positives, teeth, vector3GearProfile)
780 addCollarShaft(collarLength, derivation, elementNode, negatives, positives)
781 return extrude.getGeometryOutputByNegativesPositives(elementNode, negatives, positives)
783 extrude.addNegativesPositives(extrudeDerivation, negatives, vector3GearProfile, positives)
784 addLighteningHoles(derivation, gearHolePaths, negatives, pitchRadius, positives)
785 addCollarShaft(collarLength, derivation, elementNode, negatives, positives)
786 return extrude.getGeometryOutputByNegativesPositives(elementNode, negatives, positives)
787 if derivation.plateLength <= 0.0:
788 extrude.addNegativesPositives(extrudeDerivation, negatives, vector3GearProfile, positives)
789 return extrude.getGeometryOutputByNegativesPositives(elementNode, negatives, positives)
790 portionDirections = extrude.getSpacedPortionDirections(extrudeDerivation.interpolationDictionary)
791 outerGearProfile = vector3GearProfile[0]
792 outerLoopLists = extrude.getLoopListsByPath(extrudeDerivation, None, outerGearProfile, portionDirections)
793 addBottomLoop(-derivation.plateClearance, outerLoopLists[0])
794 geometryOutput = triangle_mesh.getPillarsOutput(outerLoopLists)
795 positives.append(geometryOutput)
796 innerLoopLists = extrude.getLoopListsByPath(extrudeDerivation, None, vector3GearProfile[1], portionDirections)
797 addBottomLoop(-derivation.plateClearance, innerLoopLists[0])
798 geometryOutput = triangle_mesh.getPillarsOutput(innerLoopLists)
799 negatives.append(geometryOutput)
800 connectionStart = Vector3(0.0, 0.0, -derivation.plateLength)
801 copyShallow = derivation.elementNode.getCopyShallow()
802 copyShallow.attributes['path'] = [connectionStart, Vector3(0.0, 0.0, -derivation.plateClearance)]
803 plateDerivation = extrude.ExtrudeDerivation(copyShallow)
804 extrude.addNegativesPositives(plateDerivation, negatives, [outerGearProfile], positives)
805 vector3LighteningHoles = getLighteningHoles(derivation, gearHolePaths, pitchRadius)
806 extrude.addNegativesPositives(plateDerivation, negatives, vector3LighteningHoles, positives)
807 addShaft(derivation, negatives, positives)
808 positiveOutput = triangle_mesh.getUnifiedOutput(positives)
809 annulusPlateOutput = {'difference' : {'shapes' : [positiveOutput] + negatives}}
810 if collarLength <= 0.0:
811 outputCylinder = solid.getGeometryOutputByManipulation(elementNode, annulusPlateOutput)
812 return getLiftedOutput(derivation, outputCylinder)
815 connectionEnd = Vector3(0.0, 0.0, derivation.faceWidth + collarLength)
816 copyShallow = derivation.elementNode.getCopyShallow()
817 copyShallow.attributes['path'] = [Vector3(0.0, 0.0, -derivation.plateClearance), connectionEnd]
818 collarDerivation = extrude.ExtrudeDerivation(copyShallow)
819 addCollarShaftSetDerivation(collarDerivation, collarLength, derivation, elementNode, negatives, positives)
820 collarOutput = {'difference' : {'shapes' : positives + negatives}}
821 cylinderOutput = {'union' : {'shapes' : [annulusPlateOutput, collarOutput]}}
822 outputCylinder = solid.getGeometryOutputByManipulation(elementNode, cylinderOutput)
823 return getLiftedOutput(derivation, outputCylinder)
825 def getOutputRack(derivation, elementNode, vector3GearProfile):
826 "Get extrude output for a rack."
828 for complexPoint in derivation.helixPath:
829 point = Vector3(derivation.helixHeight * complexPoint.imag, 0.0, derivation.faceWidth * complexPoint.real)
831 copyShallow = derivation.elementNode.getCopyShallow()
832 copyShallow.attributes['path'] = path
833 extrudeDerivation = extrude.ExtrudeDerivation(copyShallow)
836 vector3RackProfiles = [vector3GearProfile]
837 if derivation.extraRackDemilength > 0.0:
838 yMaximum = -912345678.0
839 yMinimum = 912345678.0
840 for point in vector3GearProfile:
841 yMaximum = max(point.y, yMaximum)
842 yMinimum = min(point.y, yMinimum)
843 muchLessThanWidth = 0.01 * derivation.rackWidth
844 yMaximum += muchLessThanWidth
845 yMinimum -= muchLessThanWidth
846 extraRackLength = derivation.extraRackDemilength + derivation.extraRackDemilength
847 rackDemilengthPlus = derivation.rackDemilength + extraRackLength
849 Vector3(-derivation.rackDemilength, yMaximum),
850 Vector3(-derivation.rackDemilength, yMinimum),
851 Vector3(-rackDemilengthPlus, yMinimum),
852 Vector3(-rackDemilengthPlus, yMaximum)]
853 vector3RackProfiles.append(leftNegative)
855 Vector3(rackDemilengthPlus, yMaximum),
856 Vector3(rackDemilengthPlus, yMinimum),
857 Vector3(derivation.rackDemilength, yMinimum),
858 Vector3(derivation.rackDemilength, yMaximum)]
859 vector3RackProfiles.append(rightNegative)
860 addRackHoles(derivation, elementNode, vector3RackProfiles)
861 extrude.addNegativesPositives(extrudeDerivation, negatives, vector3RackProfiles, positives)
862 return extrude.getGeometryOutputByNegativesPositives(elementNode, negatives, positives)
864 def getPathOutput(creationFirst, derivation, elementNode, translation, vector3ComplementPaths, vector3PinionProfile):
865 "Get gear path output."
866 vector3PinionProfile = lineation.getPackedGeometryOutputByLoop(elementNode, lineation.SideLoop(vector3PinionProfile))
867 if creationFirst == 'p':
868 return vector3PinionProfile
869 packedGearGeometry = []
870 for vector3ComplementPath in vector3ComplementPaths:
871 sideLoop = lineation.SideLoop(vector3ComplementPath)
872 packedGearGeometry += lineation.getPackedGeometryOutputByLoop(elementNode, sideLoop)
873 if creationFirst == 'c':
874 return packedGearGeometry
875 euclidean.translateVector3Paths(packedGearGeometry, translation)
876 return vector3PinionProfile + packedGearGeometry
878 def getThicknessMultipliedPath(path, thicknessMultiplier):
879 "Get thickness multiplied path."
880 for pointIndex, point in enumerate(path):
881 path[pointIndex] = complex(point.real * thicknessMultiplier, point.imag)
884 def getToothProfile(derivation, pitchRadius, teeth):
885 'Get profile for one tooth.'
887 return getToothProfileAnnulus(derivation, pitchRadius, teeth)
889 return getToothProfileRack(derivation)
890 return getToothProfileCylinder(derivation, pitchRadius, teeth)
892 def getToothProfileAnnulus(derivation, pitchRadius, teeth):
893 'Get profile for one tooth of an annulus.'
894 toothProfileHalf = []
895 toothProfileHalfCylinder = getToothProfileHalfCylinder(derivation, pitchRadius)
896 pitchRadius = -pitchRadius
897 innerRadius = pitchRadius - derivation.addendum
898 # tooth is multiplied by 1.02 because at around 1.01 for a 7/-23/20.0 test case, there is intersection since the paths are bending together
899 for point in getThicknessMultipliedPath(toothProfileHalfCylinder, 1.02 / derivation.toothThicknessMultiplier):
900 if abs(point) >= innerRadius:
901 toothProfileHalf.append(point)
902 profileFirst = toothProfileHalf[0]
903 profileSecond = toothProfileHalf[1]
904 firstMinusSecond = profileFirst - profileSecond
905 remainingAddendum = abs(profileFirst) - innerRadius
906 firstMinusSecond *= remainingAddendum / abs(firstMinusSecond)
907 extensionPoint = profileFirst + firstMinusSecond
908 if derivation.tipBevel > 0.0:
909 unitPolar = euclidean.getWiddershinsUnitPolar(2.0 / float(teeth) * math.pi)
910 mirrorPoint = complex(-extensionPoint.real, extensionPoint.imag) * unitPolar
911 bevelPath = getBevelPath(profileFirst, derivation.tipBevel, extensionPoint, mirrorPoint)
912 toothProfileHalf = bevelPath + toothProfileHalf
914 toothProfileHalf.insert(0, extensionPoint)
915 profileLast = toothProfileHalf[-1]
916 profilePenultimate = toothProfileHalf[-2]
917 lastMinusPenultimate = profileLast - profilePenultimate
918 remainingDedendum = pitchRadius - abs(profileLast) + derivation.dedendum
919 lastMinusPenultimate *= remainingDedendum / abs(lastMinusPenultimate)
920 extensionPoint = profileLast + lastMinusPenultimate
921 if derivation.rootBevel > 0.0:
922 mirrorPoint = complex(-extensionPoint.real, extensionPoint.imag)
923 bevelPath = getBevelPath(profileLast, derivation.rootBevel, extensionPoint, mirrorPoint)
925 toothProfileHalf += bevelPath
927 toothProfileHalf.append(extensionPoint)
928 toothProfileAnnulus = euclidean.getMirrorPath(toothProfileHalf)
929 toothProfileAnnulus.reverse()
930 return toothProfileAnnulus
932 def getToothProfileCylinder(derivation, pitchRadius, teeth):
933 'Get profile for one tooth of a cylindrical gear.'
934 toothProfileHalfCylinder = getToothProfileHalfCylinder(derivation, pitchRadius)
935 toothProfileHalfCylinder = getThicknessMultipliedPath(toothProfileHalfCylinder, derivation.toothThicknessMultiplier)
936 toothProfileHalf = []
937 innerRadius = pitchRadius - derivation.dedendum
938 for point in toothProfileHalfCylinder:
939 if abs(point) >= innerRadius:
940 toothProfileHalf.append(point)
941 return getToothProfileCylinderByProfile(derivation, pitchRadius, teeth, toothProfileHalf)
943 def getToothProfileCylinderByProfile(derivation, pitchRadius, teeth, toothProfileHalf):
944 'Get profile for one tooth of a cylindrical gear.'
945 profileFirst = toothProfileHalf[0]
946 profileSecond = toothProfileHalf[1]
947 firstMinusSecond = profileFirst - profileSecond
948 remainingDedendum = abs(profileFirst) - pitchRadius + derivation.dedendum
949 firstMinusSecond *= remainingDedendum / abs(firstMinusSecond)
950 extensionPoint = profileFirst + firstMinusSecond
951 if derivation.rootBevel > 0.0:
952 unitPolar = euclidean.getWiddershinsUnitPolar(-2.0 / float(teeth) * math.pi)
953 mirrorPoint = complex(-extensionPoint.real, extensionPoint.imag) * unitPolar
954 bevelPath = getBevelPath(profileFirst, derivation.rootBevel, extensionPoint, mirrorPoint)
955 toothProfileHalf = bevelPath + toothProfileHalf
957 toothProfileHalf.insert(0, extensionPoint)
958 if derivation.tipBevel > 0.0:
959 profileLast = toothProfileHalf[-1]
960 profilePenultimate = toothProfileHalf[-2]
961 mirrorPoint = complex(-profileLast.real, profileLast.imag)
962 bevelPath = getBevelPath(profilePenultimate, derivation.tipBevel, profileLast, mirrorPoint)
964 toothProfileHalf = toothProfileHalf[: -1] + bevelPath
965 return euclidean.getMirrorPath(toothProfileHalf)
967 def getToothProfileHalfCylinder(derivation, pitchRadius):
968 'Get profile for half of a one tooth of a cylindrical gear.'
970 # x = -y * tan(p) + 1
971 # x*x + y*y = (2-cos(p))^2
972 # y*y*t*t-2yt+1+y*y=4-4c-c*c
973 # y*y*(t*t+1)-2yt=3-4c-c*c
974 # y*y*(t*t+1)-2yt-3+4c-c*c=0
978 a = derivation.tanPressure * derivation.tanPressure + 1.0
979 b = -derivation.tanPressure - derivation.tanPressure
980 cEnd = derivation.cosPressure * (4.0 - derivation.cosPressure) - 3.0
981 yEnd = (-b - math.sqrt(b*b - 4 * a * cEnd)) * 0.5 / a
982 yEnd *= derivation.pitchRadius / abs(pitchRadius)
983 yEnd -= derivation.clearance / abs(pitchRadius)
984 # to prevent intersections, yBegin is moved towards the base circle, giving a thinner tooth
986 if pitchRadius > 0.0:
987 yBegin = 0.5 * derivation.sinPressure + 0.5 * yBegin
988 beginComplex = complex(1.0 - yBegin * derivation.tanPressure, yBegin)
989 endComplex = complex(1.0 - yEnd * derivation.tanPressure, yEnd)
990 endMinusBeginComplex = endComplex - beginComplex
991 wholeAngle = -abs(endMinusBeginComplex) / derivation.cosPressure
992 wholeAngleIncrement = wholeAngle / float(derivation.profileSurfaces)
993 stringStartAngle = abs(beginComplex - complex(1.0, 0.0)) / derivation.cosPressure
994 wholeDepthIncrementComplex = endMinusBeginComplex / float(derivation.profileSurfaces)
995 for profileIndex in xrange(derivation.profileSurfaces + 1):
996 contactPoint = beginComplex + wholeDepthIncrementComplex * float(profileIndex)
997 stringAngle = stringStartAngle + wholeAngleIncrement * float(profileIndex)
998 angle = math.atan2(contactPoint.imag, contactPoint.real) - stringAngle
999 angle += 0.5 * math.pi - derivation.quarterWavelength / abs(pitchRadius)
1000 toothPoint = abs(contactPoint) * euclidean.getWiddershinsUnitPolar(angle) * abs(pitchRadius)
1001 toothProfile.append(toothPoint)
1004 def getToothProfileRack(derivation):
1005 'Get profile for one rack tooth.'
1006 addendumSide = derivation.quarterWavelength - derivation.addendum * derivation.tanPressure
1007 addendumComplex = complex(addendumSide, derivation.addendum)
1008 dedendumSide = derivation.quarterWavelength + derivation.dedendum * derivation.tanPressure
1009 dedendumComplex = complex(dedendumSide, -derivation.dedendum)
1010 toothProfile = [dedendumComplex]
1011 if derivation.rootBevel > 0.0:
1012 mirrorPoint = complex(derivation.wavelength - dedendumSide, -derivation.dedendum)
1013 toothProfile = getBevelPath(addendumComplex, derivation.rootBevel, dedendumComplex, mirrorPoint)
1014 if derivation.tipBevel > 0.0:
1015 mirrorPoint = complex(-addendumComplex.real, addendumComplex.imag)
1016 bevelPath = getBevelPath(dedendumComplex, derivation.tipBevel, addendumComplex, mirrorPoint)
1018 toothProfile += bevelPath
1020 toothProfile.append(addendumComplex)
1021 return euclidean.getMirrorPath(getThicknessMultipliedPath(toothProfile, derivation.toothThicknessMultiplier))
1023 def processElementNode(elementNode):
1024 "Process the xml element."
1025 geometryOutput = getGeometryOutput(None, elementNode)
1026 if geometryOutput.__class__ == list:
1027 path.convertElementNode(elementNode, geometryOutput)
1029 solid.processElementNodeByGeometry(elementNode, geometryOutput)
1032 class GearDerivation:
1033 "Class to hold gear variables."
1034 def __init__(self, elementNode):
1036 self.clearanceOverWavelength = evaluate.getEvaluatedFloat(0.1, elementNode, 'clearanceOverWavelength')
1037 self.collarAddendumOverRadius = evaluate.getEvaluatedFloat(1.0, elementNode, 'collarAddendumOverRadius')
1038 self.complementCollarLengthOverFaceWidth = evaluate.getEvaluatedFloat(
1039 0.0, elementNode, 'complementCollarLengthOverFaceWidth')
1040 self.copyShallow = elementNode.getCopyShallow()
1041 self.creationType = evaluate.getEvaluatedString('both', elementNode, 'creationType')
1042 self.creationTypeMenuRadioStrings = 'both complement pinion'.split()
1043 self.elementNode = elementNode
1044 self.faceWidth = evaluate.getEvaluatedFloat(10.0, elementNode, 'faceWidth')
1045 self.helixAngle = evaluate.getEvaluatedFloat(0.0, elementNode, 'helixAngle')
1046 self.helixType = evaluate.getEvaluatedString('basic', elementNode, 'helixType')
1047 self.helixTypeMenuRadioStrings = 'basic herringbone parabolic'.split()
1048 self.keywayRadiusOverRadius = evaluate.getEvaluatedFloat(0.5, elementNode, 'keywayRadiusOverRadius')
1049 self.lighteningHoleMarginOverRimDedendum = evaluate.getEvaluatedFloat(
1050 1.0, elementNode, 'lighteningHoleMarginOverRimDedendum')
1051 self.lighteningHoleMinimumRadius = evaluate.getEvaluatedFloat(
1052 1.0, elementNode, 'lighteningHoleMinimumRadius')
1053 self.moveType = evaluate.getEvaluatedString('separate', elementNode, 'moveType')
1054 self.moveTypeMenuRadioStrings = 'mesh none separate vertical'.split()
1055 self.operatingAngle = evaluate.getEvaluatedFloat(180.0, elementNode, 'operatingAngle')
1056 self.pinionCollarLengthOverFaceWidth = evaluate.getEvaluatedFloat(
1057 0.0, elementNode, 'pinionCollarLengthOverFaceWidth')
1058 self.plateClearanceOverLength = evaluate.getEvaluatedFloat(0.2, elementNode, 'plateClearanceOverLength')
1059 self.plateLengthOverFaceWidth = evaluate.getEvaluatedFloat(0.5, elementNode, 'plateLengthOverFaceWidth')
1060 self.pressureAngle = evaluate.getEvaluatedFloat(20.0, elementNode, 'pressureAngle')
1061 self.profileSurfaces = evaluate.getEvaluatedInt(11, elementNode, 'profileSurfaces')
1062 self.rackHoleBelowOverWidth = evaluate.getEvaluatedFloat(0.6, elementNode, 'rackHoleBelowOverWidth')
1063 self.rackHoleRadiusOverWidth = evaluate.getEvaluatedFloat(0.0, elementNode, 'rackHoleRadiusOverWidth')
1064 self.rackHoleStepOverWidth = evaluate.getEvaluatedFloat(1.0, elementNode, 'rackHoleStepOverWidth')
1065 self.rackLengthOverRadius = evaluate.getEvaluatedFloat(math.pi + math.pi, elementNode, 'rackLengthOverRadius')
1066 self.rackWidthOverFaceWidth = evaluate.getEvaluatedFloat(1.0, elementNode, 'rackWidthOverFaceWidth')
1067 self.rimDedendumOverRadius = evaluate.getEvaluatedFloat(0.2, elementNode, 'rimDedendumOverRadius')
1068 self.rootBevelOverClearance = evaluate.getEvaluatedFloat(0.5, elementNode, 'rootBevelOverClearance')
1069 self.shaftDepthBottomOverRadius = evaluate.getEvaluatedFloat(0.0, elementNode, 'shaftDepthBottomOverRadius')
1070 self.shaftDepthTopOverRadius = evaluate.getEvaluatedFloat(0.0, elementNode, 'shaftDepthOverRadius')
1071 self.shaftRadiusOverPitchRadius = evaluate.getEvaluatedFloat(0.0, elementNode, 'shaftRadiusOverPitchRadius')
1072 self.shaftSides = evaluate.getEvaluatedInt(4, elementNode, 'shaftSides')
1073 self.teethComplement = evaluate.getEvaluatedInt(17, elementNode, 'teethComplement')
1074 self.teethPinion = evaluate.getEvaluatedInt(7, elementNode, 'teeth')
1075 totalTeethOverPinionTeeth = float(self.teethComplement + self.teethPinion) / float(self.teethPinion)
1076 self.centerDistance = evaluate.getEvaluatedFloat(20.0 * totalTeethOverPinionTeeth, elementNode, 'centerDistance')
1077 derivedPitchRadius = self.centerDistance / totalTeethOverPinionTeeth
1078 self.pitchRadius = evaluate.getEvaluatedFloat(derivedPitchRadius, elementNode, 'pitchRadius')
1079 self.tipBevelOverClearance = evaluate.getEvaluatedFloat(0.1, elementNode, 'tipBevelOverClearance')
1080 # tooth multiplied by 0.99999 to avoid an intersection
1081 self.toothThicknessMultiplier = evaluate.getEvaluatedFloat(0.99999, elementNode, 'toothThicknessMultiplier')
1082 # Set derived variables.
1083 self.wavelength = self.pitchRadius * 2.0 * math.pi / float(self.teethPinion)
1084 self.clearance = self.wavelength * self.clearanceOverWavelength
1085 self.clearance = evaluate.getEvaluatedFloat(self.clearance, elementNode, 'clearance')
1086 self.complementCollarLength = self.faceWidth * self.complementCollarLengthOverFaceWidth
1087 self.complementCollarLength = evaluate.getEvaluatedFloat(self.complementCollarLength, elementNode, 'complementCollarLength')
1088 self.gearHolePaths = evaluate.getTransformedPathsByKey([], elementNode, 'gearHolePaths')
1089 self.pinionCollarLength = self.faceWidth * self.pinionCollarLengthOverFaceWidth
1090 self.pinionCollarLength = evaluate.getEvaluatedFloat(self.pinionCollarLength, elementNode, 'pinionCollarLength')
1091 self.plateLength = self.faceWidth * self.plateLengthOverFaceWidth
1092 self.plateLength = evaluate.getEvaluatedFloat(self.plateLength, elementNode, 'plateLength')
1093 self.plateClearance = self.plateLength * self.plateClearanceOverLength
1094 self.plateClearance = evaluate.getEvaluatedFloat(self.plateClearance, elementNode, 'plateClearance')
1095 self.rackLength = self.pitchRadius * self.rackLengthOverRadius
1096 self.rackLength = evaluate.getEvaluatedFloat(self.rackLength, elementNode, 'rackLength')
1097 self.rackDemilength = 0.5 * self.rackLength
1098 self.rackWidth = self.faceWidth * self.rackWidthOverFaceWidth
1099 self.rackWidth = evaluate.getEvaluatedFloat(self.rackWidth, elementNode, 'rackWidth')
1100 self.rimDedendum = self.pitchRadius * self.rimDedendumOverRadius
1101 self.rimDedendum = evaluate.getEvaluatedFloat(self.rimDedendum, elementNode, 'rimDedendum')
1102 self.rootBevel = self.clearance * self.rootBevelOverClearance
1103 self.rootBevel = evaluate.getEvaluatedFloat(self.rootBevel, elementNode, 'rootBevel')
1104 self.shaftRadius = self.pitchRadius * self.shaftRadiusOverPitchRadius
1105 self.shaftRadius = evaluate.getEvaluatedFloat(self.shaftRadius, elementNode, 'shaftRadius')
1106 self.collarAddendum = self.shaftRadius * self.collarAddendumOverRadius
1107 self.collarAddendum = evaluate.getEvaluatedFloat(self.collarAddendum, elementNode, 'collarWidth')
1108 self.keywayRadius = self.shaftRadius * self.keywayRadiusOverRadius
1109 self.keywayRadius = lineation.getFloatByPrefixBeginEnd(elementNode, 'keywayRadius', 'keywayDiameter', self.keywayRadius)
1110 self.lighteningHoleMargin = self.rimDedendum * self.lighteningHoleMarginOverRimDedendum
1111 self.lighteningHoleMargin = evaluate.getEvaluatedFloat(
1112 self.lighteningHoleMargin, elementNode, 'lighteningHoleMargin')
1113 self.rackHoleBelow = self.rackWidth * self.rackHoleBelowOverWidth
1114 self.rackHoleBelow = evaluate.getEvaluatedFloat(self.rackHoleBelow, elementNode, 'rackHoleBelow')
1115 self.rackHoleRadius = self.rackWidth * self.rackHoleRadiusOverWidth
1116 self.rackHoleRadius = lineation.getFloatByPrefixBeginEnd(elementNode, 'rackHoleRadius', 'rackHoleDiameter', self.rackHoleRadius)
1117 self.rackHoleStep = self.rackWidth * self.rackHoleStepOverWidth
1118 self.rackHoleStep = evaluate.getEvaluatedFloat(self.rackHoleStep, elementNode, 'rackHoleStep')
1119 self.shaftDepthBottom = self.shaftRadius * self.shaftDepthBottomOverRadius
1120 self.shaftDepthBottom = evaluate.getEvaluatedFloat(self.shaftDepthBottom, elementNode, 'shaftDepthBottom')
1121 self.shaftDepthTop = self.shaftRadius * self.shaftDepthTopOverRadius
1122 self.shaftDepthTop = evaluate.getEvaluatedFloat(self.shaftDepthTop, elementNode, 'shaftDepthTop')
1123 self.shaftPath = evaluate.getTransformedPathByKey([], elementNode, 'shaftPath')
1124 if len(self.shaftPath) < 3:
1125 self.shaftPath = shaft.getShaftPath(self.shaftDepthBottom, self.shaftDepthTop, self.shaftRadius, -self.shaftSides)
1126 self.tipBevel = self.clearance * self.tipBevelOverClearance
1127 self.tipBevel = evaluate.getEvaluatedFloat(self.tipBevel, elementNode, 'tipBevel')
1128 # Set derived values.
1129 self.helixRadian = math.radians(self.helixAngle)
1130 if self.teethComplement <= 0.0 and self.operatingAngle != 180.0:
1131 print('Warning, an operatingAngle other than 180 degrees can only work with a positive number of gear teeth.')
1132 print('Therefore the operatingAngle will be reset to 180 degrees.')
1133 self.operatingAngle = 180.0
1134 self.tanHelix = math.tan(self.helixRadian)
1135 self.helixHeight = self.tanHelix * self.faceWidth
1136 self.operatingRadian = math.radians(self.operatingAngle)
1137 self.pitchRadiusComplement = self.pitchRadius * float(self.teethComplement) / float(self.teethPinion)
1138 self.pressureRadian = math.radians(self.pressureAngle)
1139 self.cosPressure = math.cos(self.pressureRadian)
1140 self.sinPressure = math.sin(self.pressureRadian)
1141 self.tanPressure = math.tan(self.pressureRadian)
1142 self.halfWavelength = 0.5 * self.wavelength
1143 self.helixPath = euclidean.getComplexPath(evaluate.getTransformedPathByKey([], elementNode, 'helixPath'))
1144 if len(self.helixPath) < 1:
1145 self.helixPath = getHelixComplexPath(self, elementNode)
1146 self.quarterWavelength = 0.25 * self.wavelength
1147 self.shaftRimRadius = self.shaftRadius + self.collarAddendum
1148 self.toothProfileHalf = getToothProfileHalfCylinder(self, self.pitchRadius)
1149 self.toothProfileHalf = getThicknessMultipliedPath(self.toothProfileHalf, self.toothThicknessMultiplier)
1150 self.addendum = self.toothProfileHalf[-1].imag - self.pitchRadius
1151 self.dedendum = abs(self.toothProfileHalf[-1]) - self.pitchRadius + self.clearance
1152 self.pinionToothProfile = getToothProfileCylinderByProfile(self, self.pitchRadius, self.teethPinion, self.toothProfileHalf)