add timing gear t-shape

This commit is contained in:
looooo
2024-01-02 00:02:42 +01:00
parent 17715c0754
commit 9e14aac76b
6 changed files with 544 additions and 9 deletions

View File

@@ -19,14 +19,13 @@
import os
import FreeCAD
import FreeCADGui as Gui
from .features import (
ViewProviderGear,
InvoluteGear,
InternalInvoluteGear,
InvoluteGearRack,
CycloidGearRack,
)
from .features import (
CycloidGear,
BevelGear,
CrownGear,
@@ -36,6 +35,8 @@ from .features import (
HypoCycloidGear,
BaseGear,
)
from .timing_gear_t import TimingGearT
from .connector import GearConnector, ViewProviderGearConnector
@@ -167,6 +168,14 @@ class CreateWormGear(BaseCommand):
ToolTip = "Create a Worm gear"
class CreateTimingGearT(BaseCommand):
NAME = "TimingGearT"
GEAR_FUNCTION = TimingGearT
Pixmap = os.path.join(BaseCommand.ICONDIR, "timinggear_t.svg")
MenuText = "Timing Gear T-shape"
ToolTip = "Create a Timing gear T-shape"
class CreateTimingGear(BaseCommand):
NAME = "TimingGear"
GEAR_FUNCTION = TimingGear

View File

@@ -16,7 +16,6 @@
# * *
# ***************************************************************************
from __future__ import division
import os
import sys

View File

@@ -0,0 +1,404 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
sodipodi:docname="timinggeart.svg"
inkscape:version="1.2 (dc2aeda, 2022-05-15)"
version="1.1"
id="svg3799"
height="64px"
width="64px"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="7.7781746"
inkscape:cx="37.21953"
inkscape:cy="26.870058"
inkscape:current-layer="svg3799"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:snap-center="false"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="1388"
inkscape:window-height="872"
inkscape:window-x="52"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:object-paths="true"
inkscape:object-nodes="true"
inkscape:snap-intersection-paths="true"
inkscape:snap-nodes="false"
inkscape:snap-others="true"
inkscape:lockguides="false"
inkscape:document-rotation="0"
inkscape:showpageshadow="2"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1">
<sodipodi:guide
id="guide3783"
position="32.035283,43.640454"
orientation="1,0"
inkscape:locked="false" />
<sodipodi:guide
id="guide3785"
position="32,32"
orientation="0,1"
inkscape:locked="false" />
<sodipodi:guide
id="guide9301"
position="0,0"
orientation="1,0"
inkscape:locked="false" />
<sodipodi:guide
id="guide9303"
position="0,0"
orientation="0,1"
inkscape:locked="false" />
<sodipodi:guide
id="guide9305"
position="0,64"
orientation="0,1"
inkscape:locked="false" />
<sodipodi:guide
id="guide9307"
position="64,64"
orientation="1,0"
inkscape:locked="false" />
<sodipodi:guide
position="51.168818,70.453548"
orientation="1,0"
id="guide4358"
inkscape:locked="false" />
</sodipodi:namedview>
<defs
id="defs3801">
<inkscape:path-effect
is_visible="true"
id="path-effect9409"
effect="spiro" />
<inkscape:path-effect
is_visible="true"
id="path-effect9405"
effect="spiro" />
<inkscape:path-effect
is_visible="true"
id="path-effect9398"
effect="spiro" />
<inkscape:path-effect
is_visible="true"
id="path-effect9390"
effect="spiro" />
<inkscape:path-effect
is_visible="true"
id="path-effect9384"
effect="spiro" />
<linearGradient
id="linearGradient9347"
inkscape:collect="always">
<stop
id="stop9349"
offset="0"
style="stop-color:#0079ff;stop-opacity:1;" />
<stop
id="stop9351"
offset="1"
style="stop-color:#0079ff;stop-opacity:0" />
</linearGradient>
<marker
style="overflow:visible"
id="Arrow2Mstart"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mstart">
<path
transform="scale(0.6) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round"
id="path4317" />
</marker>
<marker
style="overflow:visible;"
id="Arrow1Mend"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Mend">
<path
transform="scale(0.4) rotate(180) translate(10,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path4302" />
</marker>
<marker
style="overflow:visible;"
id="Arrow2Mend"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend">
<path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
id="path4320" />
</marker>
<marker
style="overflow:visible"
id="Arrow1Mstart"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Mstart">
<path
transform="scale(0.4) translate(10,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path4299" />
</marker>
<marker
style="overflow:visible;"
id="Arrow1Lend"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Lend">
<path
transform="scale(0.8) rotate(180) translate(12.5,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path4296" />
</marker>
<marker
style="overflow:visible;"
id="Arrow2Lend"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Lend">
<path
transform="scale(1.1) rotate(180) translate(1,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
id="path4314" />
</marker>
<marker
style="overflow:visible"
id="EmptyTriangleOutL"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="EmptyTriangleOutL">
<path
transform="scale(0.8) translate(-6,0)"
style="fill-rule:evenodd;fill:#FFFFFF;stroke:#000000;stroke-width:1.0pt"
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
id="path4487" />
</marker>
<marker
style="overflow:visible"
id="DotS"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="DotS">
<path
transform="scale(0.2) translate(7.4, 1)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt"
d="M -2.5,-1.0 C -2.5,1.7600000 -4.7400000,4.0 -7.5,4.0 C -10.260000,4.0 -12.5,1.7600000 -12.5,-1.0 C -12.5,-3.7600000 -10.260000,-6.0 -7.5,-6.0 C -4.7400000,-6.0 -2.5,-3.7600000 -2.5,-1.0 z "
id="path4394" />
</marker>
<marker
style="overflow:visible"
id="DotL"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="DotL">
<path
transform="scale(0.8) translate(7.4, 1)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt"
d="M -2.5,-1.0 C -2.5,1.7600000 -4.7400000,4.0 -7.5,4.0 C -10.260000,4.0 -12.5,1.7600000 -12.5,-1.0 C -12.5,-3.7600000 -10.260000,-6.0 -7.5,-6.0 C -4.7400000,-6.0 -2.5,-3.7600000 -2.5,-1.0 z "
id="path4388" />
</marker>
<marker
style="overflow:visible"
id="Tail"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Tail">
<g
transform="scale(-1.2)"
id="g4363">
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.8;stroke-linecap:round"
d="M -3.8048674,-3.9585227 L 0.54352094,0"
id="path4365" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.8;stroke-linecap:round"
d="M -1.2866832,-3.9585227 L 3.0617053,0"
id="path4367" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.8;stroke-linecap:round"
d="M 1.3053582,-3.9585227 L 5.6537466,0"
id="path4369" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.8;stroke-linecap:round"
d="M -3.8048674,4.1775838 L 0.54352094,0.21974226"
id="path4371" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.8;stroke-linecap:round"
d="M -1.2866832,4.1775838 L 3.0617053,0.21974226"
id="path4373" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.8;stroke-linecap:round"
d="M 1.3053582,4.1775838 L 5.6537466,0.21974226"
id="path4375" />
</g>
</marker>
<marker
style="overflow:visible"
id="Arrow1Sstart"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Sstart">
<path
transform="scale(0.2) translate(6,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path4339" />
</marker>
<marker
style="overflow:visible"
id="Arrow1Lstart"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Lstart">
<path
transform="scale(0.8) translate(12.5,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path4327" />
</marker>
<marker
style="overflow:visible"
id="Arrow1Mstart-9"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Mstart">
<path
transform="matrix(0.4,0,0,0.4,4,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
id="path4299-1"
inkscape:connector-curvature="0" />
</marker>
<marker
style="overflow:visible"
id="Arrow2Mend-7"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Mend">
<path
transform="scale(-0.6,-0.6)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
id="path4320-8"
inkscape:connector-curvature="0" />
</marker>
<linearGradient
gradientUnits="userSpaceOnUse"
y2="47.081963"
x2="1.8271284"
y1="40.800289"
x1="-21.345743"
id="linearGradient9353"
xlink:href="#linearGradient9347"
inkscape:collect="always" />
</defs>
<metadata
id="metadata3804">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
inkscape:label="Layer 1"
id="layer1">
<rect
ry="15.401461"
y="1.4630233e-07"
x="0.18181612"
height="63.986015"
width="63.804237"
id="rect3156"
style="fill:#ffbf00;stroke:none;fill-opacity:1" />
<text
xml:space="preserve"
style="font-style:italic;font-family:sans-serif;-inkscape-font-specification:'sans-serif Italic';fill:#cccccc;fill-opacity:0;stroke:#000000;stroke-width:1.00157;stroke-opacity:0.715356"
x="53.868679"
y="46.154789"
id="text539"><tspan
sodipodi:role="line"
id="tspan537"
x="53.868679"
y="46.154789" /></text>
</g>
<g
id="g145"
transform="matrix(0.23119221,0,0,0.23119221,-46.22244,84.315861)">
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:173.016px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:4.32541"
x="216.54584"
y="-169.60706"
id="text84"><tspan
sodipodi:role="line"
id="tspan82"
x="216.54584"
y="-169.60706"
style="stroke-width:4.32541">GT</tspan></text>
<text
id="text268"
y="-117.81893"
x="271.62177"
style="font-style:normal;font-weight:normal;font-size:322.964px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:4.32541"
xml:space="preserve"><tspan
style="font-size:322.964px;fill:#ff0000;stroke-width:4.32541"
y="-117.81893"
x="271.62177"
id="tspan266"
sodipodi:role="line" /></text>
</g>
<path
style="fill:#dea600;fill-opacity:0.815686;stroke:#000000;stroke-width:1.00157;stroke-opacity:0.715356"
d="m 55.411459,40.883628 c 0,0.34284 0.04434,0.688559 0,1.028519 -0.08479,0.650049 -0.266681,1.283813 -0.385695,1.928473 -0.395262,2.141004 -0.809412,4.278999 -1.157084,6.428244 -0.12394,0.766176 -0.152263,1.545148 -0.25713,2.314167 -0.149352,1.095253 -0.128564,0.09608 -0.128564,0.77139"
id="path1211" />
<path
style="fill:#dea600;fill-opacity:0.815686;stroke:#000000;stroke-width:1.00157;stroke-opacity:0.715356"
d="m 51.040253,44.483445 c 2.100653,-0.107776 4.203401,0.128565 6.299679,0.128565"
id="path1213" />
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -105,6 +105,7 @@ class GearWorkbench(Workbench):
"CreateBevelGear",
"CreateCrownGear",
"CreateWormGear",
"CreateTimingGearT",
"CreateTimingGear",
"CreateLanternGear",
"CreateHypoCycloidGear",
@@ -119,15 +120,20 @@ class GearWorkbench(Workbench):
CreateCycloidGear,
CreateInvoluteGear,
CreateInternalInvoluteGear,
CreateBevelGear,
CreateInvoluteRack,
CreateCrownGear,
CreateWormGear,
CreateTimingGearT,
CreateTimingGear,
CreateLanternGear,
CreateHypoCycloidGear,
CreateCycloidRack,
CreateGearConnector
)
from .commands import CreateBevelGear, CreateInvoluteRack, CreateCrownGear
from .commands import CreateWormGear, CreateTimingGear, CreateLanternGear
from .commands import CreateHypoCycloidGear, CreateCycloidRack
from .commands import CreateGearConnector
self.appendToolbar("Gear", self.commands)
self.appendMenu("Gear", self.commands)
# Gui.addIconPath(App.getHomePath()+"Mod/gear/icons/")
Gui.addCommand("CreateInvoluteGear", CreateInvoluteGear())
Gui.addCommand("CreateInternalInvoluteGear", CreateInternalInvoluteGear())
Gui.addCommand("CreateCycloidGear", CreateCycloidGear())
@@ -136,6 +142,7 @@ class GearWorkbench(Workbench):
Gui.addCommand("CreateInvoluteRack", CreateInvoluteRack())
Gui.addCommand("CreateCrownGear", CreateCrownGear())
Gui.addCommand("CreateWormGear", CreateWormGear())
Gui.addCommand("CreateTimingGearT", CreateTimingGearT())
Gui.addCommand("CreateTimingGear", CreateTimingGear())
Gui.addCommand("CreateLanternGear", CreateLanternGear())
Gui.addCommand("CreateHypoCycloidGear", CreateHypoCycloidGear())

View File

@@ -0,0 +1,113 @@
# -*- coding: utf-8 -*-
# ***************************************************************************
# * *
# * This program is free software: you can redistribute it and/or modify *
# * it under the terms of the GNU General Public License as published by *
# * the Free Software Foundation, either version 3 of the License, or *
# * (at your option) any later version. *
# * *
# * This program is distributed in the hope that it will be useful, *
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
# * GNU General Public License for more details. *
# * *
# * You should have received a copy of the GNU General Public License *
# * along with this program. If not, see <http://www.gnu.org/licenses/>. *
# * *
# ***************************************************************************
import numpy as np
import scipy as sp
import FreeCAD as App
import Part
from pygears._functions import (
rotation,
reflection
)
from .features import BaseGear, fcvec
class TimingGearT(BaseGear):
def __init__(self, obj):
print("hello gear")
obj.addProperty("App::PropertyLength", "pitch", "base", "pitch of gear")
obj.addProperty("App::PropertyInteger", "teeth", "base", "number of teeth")
obj.addProperty("App::PropertyLength", "tooth_height", "base", "radial height of tooth")
obj.addProperty("App::PropertyLength", "u", "base", "radial distance from tooth-head to pitch circle")
obj.addProperty("App::PropertyAngle", "alpha", "base", "angle of tooth flanks")
obj.addProperty("App::PropertyLength", "height", "base", "extrusion height")
obj.pitch = "5. mm"
obj.teeth = 15
obj.tooth_height = "1.2 mm"
obj.u = "0.6 mm"
obj.alpha = "40. deg"
obj.height = "5 mm"
self.obj = obj
obj.Proxy = self
def generate_gear_shape(self, fp):
print("generate gear shape")
pitch = fp.pitch.Value
teeth = fp.teeth
u = fp.u.Value
tooth_height = fp.tooth_height.Value
alpha = fp.alpha.Value / 180. * np.pi # we need radiant
height = fp.height.Value
r_p = pitch * teeth / 2. / np.pi
gamma_0 = pitch / r_p
gamma_1 = gamma_0 / 4
p_A = np.array([
np.cos(-gamma_1),
np.sin(-gamma_1)
]) * (r_p - u - tooth_height / 2)
def line(s):
p = p_A + np.array([
np.cos(alpha / 2 - gamma_1),
np.sin(alpha / 2 - gamma_1)
]) * s
return p
def dist_p1(s):
return (np.linalg.norm(line(s)) - (r_p - u - tooth_height)) ** 2
def dist_p2(s):
return (np.linalg.norm(line(s)) - (r_p - u)) ** 2
s1 = sp.optimize.minimize(dist_p1, 0.).x
s2 = sp.optimize.minimize(dist_p2, 0.).x
p_1 = line(s1)
p_2 = line(s2)
mirror = reflection(0.) # reflect the points at the x-axis
p_3, p_4 = mirror(np.array([p_2, p_1]))
rot = rotation(-gamma_0) # why is the rotation in wrong direction ???
p_5 = rot(np.array([p_1]))[0] # the rotation expects a list of points
l1 = Part.LineSegment(fcvec(p_1), fcvec(p_2)).toShape()
l2 = Part.LineSegment(fcvec(p_2), fcvec(p_3)).toShape()
l3 = Part.LineSegment(fcvec(p_3), fcvec(p_4)).toShape()
l4 = Part.LineSegment(fcvec(p_4), fcvec(p_5)).toShape()
w = Part.Wire([l1, l2, l3, l4])
# now using a FreeCAD Matrix (this will turn in the right direction)
rot = App.Matrix()
rot.rotateZ(gamma_0)
wires = []
for i in range(teeth):
w = w.transformGeometry(rot)
wires.append(w.copy())
contour = Part.Wire(wires)
if height == 0:
return contour
else:
face = Part.Face(Part.Wire(wires))
return face.extrude(App.Vector(0., 0., height))

View File

@@ -22,9 +22,11 @@ from numpy.linalg import solve, norm
def reflection(angle):
mat = array([[cos(2 * angle), -sin(2 * angle)], [-sin(2 * angle), -cos(2 * angle)]])
mat = array([[cos(2 * angle), -sin(2 * angle)],
[-sin(2 * angle), -cos(2 * angle)]])
def func(x):
# why not use mat @ x???
return dot(x, mat)
return func
@@ -40,6 +42,7 @@ def reflection3D(angle):
)
def func(x):
# why not use mat @ x
return dot(x, mat)
return func