10 Commits

Author SHA1 Message Date
lorenz
e1c80bd963 add spicy dependency 2022-06-11 18:25:41 +02:00
lorenz
109df352a9 InvoluteGearRack: properties_from_tool default = False 2022-05-03 14:48:05 +02:00
looooo
165f1a0aea add package.xml 2022-02-24 08:39:28 +01:00
Jonas Bähr
8258477645 add head parameter for cycloide gear
This is a backport of commit 9ddd493b from develop, with two changes:
- unrelated changes have not been back ported
- backwards compatibility was added

Note that the actual usage of the head value in pygear is wrong, though:
As it is added to the diameter (not the radius) it should have been added
twice. However, as the clearance suffers from the same bug, I choose to
stay consistent. A fix should address both, head and clearance, but this
is out of scope here.
2022-01-04 20:08:35 +01:00
Jonas Bähr
6ce203ea8f Make gear creation "undoable"
Right now, the tool tip is used as transaction name, which matches the
wording "Create a new sketch". There doesn't seem to be consistency
though FreeCAD's other workbenches, though.
2021-10-23 01:43:24 +02:00
Jonas Bähr
69ff30d65e gitignore VIM swap files 2021-10-23 01:43:24 +02:00
lorenz
3c86d12dc7 fix lgtm allert 2021-09-30 18:12:29 +02:00
Jonas Bähr
d489dfb841 Fix crown gear preview mode in PartDesign Bodies
Previously, the `preview_mode` of the crown gear returned a compound of
the base and the cut-outs. This caused problems in PD::Bodies where a
single solid is requried.
The solution in this commit changes the preview_mode to only output the
base, not generating the cutout shapes at all. This is consistent with
the involute gears having "simple=true" and saves again 0.5 Seconds
processsing time on my system using defaults (15 teeth, 4 loft profiles).

In addition, "preview = false" is also speed up by first collecting all
cut-outs, and then passing them all at once to a single cut operation.
This reduced the cutting time from 3.0 Seconds to 2.2 Seconds here.
So preview now generats the shape immediately (0.0008s vs 0.5s) and the
actual crown is generated in 2.7s instead of 3.5s (again, using the
defaut parameters, measued via Python's time.perf_counter).
2021-07-25 16:33:58 +02:00
Jonas Bähr
1b19d16264 Extend the "additiveness" to all gears when used in PD:Bodies
There are still some issues when the generated Shape is not a solid,
e.g. in the preview mode of the Crown Gear.
2021-07-25 16:33:58 +02:00
Jonas Bähr
d5e12ef116 First proof of concept of "additive gears" in PartDesign bodies
In this PoC only the involute gears work, and there is still a lot of
cleanup pending.
What does work, however, is that those gears now play nicely with
PartDesign's concept of stacking features onto each other, i.e. that the
result of a feature is the fusion of all previous ones.

Special Thanks goes to DeepSOIC for his tutorial in the forum at [1] as
well as this Part-o-Matic which showed me how this works in real live [2]
[1]: https://forum.freecadweb.org/viewtopic.php?f=22&t=21097#p163340
[2]: https://github.com/DeepSOIC/Part-o-magic/blob/master/PartOMagic/Features/PartDesign/PDShapeFeature.py
2021-07-25 16:33:58 +02:00
19 changed files with 458 additions and 2541 deletions

3
.gitignore vendored
View File

@@ -59,3 +59,6 @@ target/
.ipynb_checkpoints/
results/
*.vtk
# VIM
*.swp

View File

@@ -26,10 +26,6 @@ __python > 3 (for python2 use branch py2)__
![cycloid-gear](examples/cycloid-gear.png)
### Cycloid Rack
![cycloid-rack](examples/cycloid-rack.png)
### Spherical Involute Bevel-Gear
* Spiral

View File

@@ -1,6 +0,0 @@
#TODO:
## refactoring
- [ ] fp.gear.z -> fp.gear.num_teeth
- [ ] fp.teeth -> fp.gear.num_teeth

Binary file not shown.

Before

Width:  |  Height:  |  Size: 188 KiB

View File

@@ -1,18 +1,21 @@
# -*- 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 free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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. *
# * 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 Library 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/>. *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************

View File

@@ -1,27 +1,29 @@
# -*- 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 free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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. *
# * 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 Library 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/>. *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
import os
import FreeCAD
import FreeCADGui as Gui
from .features import ViewProviderGear, InvoluteGear, InternalInvoluteGear, InvoluteGearRack, CycloidGearRack
from .features import CycloidGear, BevelGear, CrownGear, WormGear, TimingGear, LanternGear, HypoCycloidGear, BaseGear
from .connector import GearConnector, ViewProviderGearConnector
from .features import ViewProviderGear, InvoluteGear, InvoluteGearRack
from .features import CycloidGear, BevelGear, CrownGear, WormGear, TimingGear, LanternGear, HypoCycloidGear
class BaseCommand(object):
@@ -39,10 +41,13 @@ class BaseCommand(object):
return True
def Activated(self):
doc = FreeCAD.ActiveDocument
Gui.doCommandGui("import freecad.gears.commands")
doc.openTransaction(self.ToolTip)
Gui.doCommandGui("freecad.gears.commands.{}.create()".format(
self.__class__.__name__))
FreeCAD.ActiveDocument.recompute()
doc.commitTransaction()
doc.recompute()
Gui.SendMsgToActiveView("ViewFit")
@classmethod
@@ -57,7 +62,7 @@ class BaseCommand(object):
obj = FreeCAD.ActiveDocument.addObject("PartDesign::FeaturePython", cls.NAME)
else:
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", cls.NAME)
ViewProviderGear(obj.ViewObject, cls.Pixmap)
ViewProviderGear(obj.ViewObject)
cls.GEAR_FUNCTION(obj)
if body:
@@ -76,108 +81,70 @@ class BaseCommand(object):
class CreateInvoluteGear(BaseCommand):
NAME = "InvoluteGear"
NAME = "involutegear"
GEAR_FUNCTION = InvoluteGear
Pixmap = os.path.join(BaseCommand.ICONDIR, 'involutegear.svg')
MenuText = 'Involute Gear'
ToolTip = 'Create an external involute gear'
class CreateInternalInvoluteGear(BaseCommand):
NAME = "InternalInvoluteGear"
GEAR_FUNCTION = InternalInvoluteGear
Pixmap = os.path.join(BaseCommand.ICONDIR, 'internalinvolutegear.svg')
MenuText = 'Internal Involute Gear'
ToolTip = 'Create an internal involute gear'
MenuText = 'Involute gear'
ToolTip = 'Create an Involute gear'
class CreateInvoluteRack(BaseCommand):
NAME = "InvoluteRack"
NAME = "involuterack"
GEAR_FUNCTION = InvoluteGearRack
Pixmap = os.path.join(BaseCommand.ICONDIR, 'involuterack.svg')
MenuText = 'Involute Rack'
MenuText = 'Involute rack'
ToolTip = 'Create an Involute rack'
class CreateCycloidRack(BaseCommand):
NAME = "CycloidRack"
GEAR_FUNCTION = CycloidGearRack
Pixmap = os.path.join(BaseCommand.ICONDIR, 'cycloidrack.svg')
MenuText = 'Cycloid Rack'
ToolTip = 'Create an Cycloid rack'
class CreateCrownGear(BaseCommand):
NAME = "CrownGear"
NAME = "crowngear"
GEAR_FUNCTION = CrownGear
Pixmap = os.path.join(BaseCommand.ICONDIR, 'crowngear.svg')
MenuText = 'Crown Gear'
MenuText = 'Crown gear'
ToolTip = 'Create a Crown gear'
class CreateCycloidGear(BaseCommand):
NAME = "CycloidGear"
NAME = "cycloidgear"
GEAR_FUNCTION = CycloidGear
Pixmap = os.path.join(BaseCommand.ICONDIR, 'cycloidgear.svg')
MenuText = 'Cycloid Gear'
MenuText = 'Cycloid gear'
ToolTip = 'Create a Cycloid gear'
class CreateBevelGear(BaseCommand):
NAME = "BevelGear"
NAME = "bevelgear"
GEAR_FUNCTION = BevelGear
Pixmap = os.path.join(BaseCommand.ICONDIR, 'bevelgear.svg')
MenuText = 'Bevel Gear'
MenuText = 'Bevel gear'
ToolTip = 'Create a Bevel gear'
class CreateHypoCycloidGear(BaseCommand):
NAME = "HypocycloidGear"
NAME = "hypocycloidgear"
GEAR_FUNCTION = HypoCycloidGear
Pixmap = os.path.join(BaseCommand.ICONDIR, 'hypocycloidgear.svg')
MenuText = 'HypoCycloid Gear'
MenuText = 'HypoCycloid gear'
ToolTip = 'Create a HypoCycloid gear with its pins'
class CreateWormGear(BaseCommand):
NAME = "WormGear"
NAME = "wormgear"
GEAR_FUNCTION = WormGear
Pixmap = os.path.join(BaseCommand.ICONDIR, 'wormgear.svg')
MenuText = 'Worm Gear'
MenuText = 'Worm gear'
ToolTip = 'Create a Worm gear'
class CreateTimingGear(BaseCommand):
NAME = "TimingGear"
NAME = "timinggear"
GEAR_FUNCTION = TimingGear
Pixmap = os.path.join(BaseCommand.ICONDIR, 'timinggear.svg')
MenuText = 'Timing Gear'
MenuText = 'Timing gear'
ToolTip = 'Create a Timing gear'
class CreateLanternGear(BaseCommand):
NAME = "LanternGear"
NAME = "lanterngear"
GEAR_FUNCTION = LanternGear
Pixmap = os.path.join(BaseCommand.ICONDIR, 'lanterngear.svg')
MenuText = 'Lantern Gear'
MenuText = 'Lantern gear'
ToolTip = 'Create a Lantern gear'
class CreateGearConnector(BaseCommand):
NAME = "GearConnector"
GEAR_FUNCTION = GearConnector
Pixmap = os.path.join(BaseCommand.ICONDIR, 'gearconnector.svg')
MenuText = 'Combine two gears'
ToolTip = 'Combine two gears'
def Activated(self):
gear1 = Gui.Selection.getSelection()[0]
assert isinstance(gear1.Proxy, BaseGear)
gear2 = Gui.Selection.getSelection()[1]
assert isinstance(gear2.Proxy, BaseGear)
# check if selected objects are beams
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", self.NAME)
GearConnector(obj, gear1, gear2)
ViewProviderGearConnector(obj.ViewObject)
FreeCAD.ActiveDocument.recompute()
return obj

View File

@@ -1,161 +0,0 @@
# -*- 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 os
import copy
import numpy as np
import FreeCAD
from pygears import __version__
from .features import InvoluteGear, CycloidGear, InvoluteGearRack, CycloidGearRack, InternalInvoluteGear
from pygears.computation import compute_shifted_gears
class ViewProviderGearConnector(object):
def __init__(self, vobj, icon_fn=None):
# Set this object to the proxy object of the actual view provider
vobj.Proxy = self
dirname = os.path.dirname(__file__)
self.icon_fn = icon_fn or os.path.join(dirname, "icons", "gearconnector.svg")
def attach(self, vobj):
self.vobj = vobj
def getIcon(self):
return self.icon_fn
def __getstate__(self):
return {"icon_fn": self.icon_fn}
def __setstate__(self, state):
self.icon_fn = state["icon_fn"]
class GearConnector(object):
def __init__(self, obj, master_gear, slave_gear):
obj.addProperty("App::PropertyString", "version", "version", "freecad.gears-version", 1)
obj.addProperty("App::PropertyLink","master_gear","gear","master gear", 1)
obj.addProperty("App::PropertyLink","slave_gear","gear","slave gear", 1)
obj.addProperty("App::PropertyAngle", "angle1", "gear", "angle at which second gear is placed", 0)
obj.addProperty("App::PropertyAngle", "angle2", "gear", "angle at which second gear is placed", 1)
obj.version = __version__
obj.master_gear = master_gear
obj.slave_gear = slave_gear
obj.angle1 = 0
obj.angle2 = 0
obj.Proxy = self
def onChanged(self, fp, prop):
# fp.angle2 = fp.master_gear.Placement.Rotation.Angle
if isinstance(fp.master_gear.Proxy, InvoluteGear) and isinstance(fp.slave_gear.Proxy, InvoluteGear):
angle_master = fp.master_gear.Placement.Rotation.Angle * sum(fp.master_gear.Placement.Rotation.Axis)
dw_master = fp.master_gear.dw
dw_slave = fp.slave_gear.dw
dist = (dw_master + dw_slave) / 2
if fp.master_gear.shift != 0 or fp.slave_gear.shift != 0:
dist, alpha_w = compute_shifted_gears(
fp.master_gear.module,
np.deg2rad(fp.master_gear.pressure_angle.Value),
fp.master_gear.teeth,
fp.slave_gear.teeth,
fp.master_gear.shift,
fp.slave_gear.shift)
mat0 = FreeCAD.Matrix() # unity matrix
trans = FreeCAD.Vector(dist)
mat0.move(trans)
rot = FreeCAD.Rotation(FreeCAD.Vector(0,0,1), fp.angle1).toMatrix()
angle2 = dw_master / dw_slave * fp.angle1.Value
angle4 = dw_master / dw_slave * np.rad2deg(angle_master)
rot2 = FreeCAD.Rotation(FreeCAD.Vector(0,0,1), angle2).toMatrix()
angle3 = abs(fp.slave_gear.teeth % 2 - 1) * 180. / fp.slave_gear.teeth
rot3 = FreeCAD.Rotation(FreeCAD.Vector(0,0,1), angle3).toMatrix()
rot4 = FreeCAD.Rotation(FreeCAD.Vector(0,0,1), -angle4).toMatrix()
mat1 = rot * mat0 * rot2 * rot3 * rot4
mat1.move(fp.master_gear.Placement.Base)
fp.slave_gear.Placement = mat1
if isinstance(fp.master_gear.Proxy, InternalInvoluteGear) and isinstance(fp.slave_gear.Proxy, InvoluteGear):
angle_master = fp.master_gear.Placement.Rotation.Angle * sum(fp.master_gear.Placement.Rotation.Axis)
dw_master = fp.master_gear.dw
dw_slave = fp.slave_gear.dw
dist = (dw_master - dw_slave) / 2
if fp.master_gear.shift != 0 or fp.slave_gear.shift != 0:
dist, alpha_w = compute_shifted_gears(
fp.master_gear.module,
np.deg2rad(fp.master_gear.pressure_angle.Value),
fp.master_gear.teeth,
fp.slave_gear.teeth,
fp.master_gear.shift,
fp.slave_gear.shift)
mat0 = FreeCAD.Matrix() # unity matrix
trans = FreeCAD.Vector(dist)
mat0.move(trans)
rot = FreeCAD.Rotation(FreeCAD.Vector(0,0,1), fp.angle1).toMatrix()
angle2 = -dw_master / dw_slave * fp.angle1.Value
angle4 = -dw_master / dw_slave * np.rad2deg(angle_master)
rot2 = FreeCAD.Rotation(FreeCAD.Vector(0,0,1), angle2).toMatrix()
angle3 = abs(fp.slave_gear.teeth % 2 - 1) * 180. / fp.slave_gear.teeth
rot3 = FreeCAD.Rotation(FreeCAD.Vector(0,0,1), angle3).toMatrix()
rot4 = FreeCAD.Rotation(FreeCAD.Vector(0,0,1), -angle4).toMatrix()
mat1 = rot * mat0 * rot2 * rot3 * rot4
mat1.move(fp.master_gear.Placement.Base)
fp.slave_gear.Placement = mat1
if ((isinstance(fp.master_gear.Proxy, InvoluteGear) and isinstance(fp.slave_gear.Proxy, InvoluteGearRack))
or (isinstance(fp.master_gear.Proxy, CycloidGear) and isinstance(fp.slave_gear.Proxy, CycloidGearRack))):
angle_master = fp.master_gear.Placement.Rotation.Angle * sum(fp.master_gear.Placement.Rotation.Axis)
dw_master = fp.master_gear.dw.Value
dw_slave = 0
dist = -(dw_master + dw_slave) / 2
mat0 = FreeCAD.Matrix() # unity matrix
mat0.move(FreeCAD.Vector(dist, 0, 0))
mat1 = FreeCAD.Matrix()
mat1.move(FreeCAD.Vector(0, np.deg2rad(fp.angle1.Value) * dw_master / 2, 0))
mat2 = FreeCAD.Matrix()
mat2.move(FreeCAD.Vector(0, -np.deg2rad(fp.angle2.Value) * dw_master / 2, 0))
rot = FreeCAD.Rotation(FreeCAD.Vector(0,0,1), fp.angle1).toMatrix()
mat3 = rot * mat2 *mat1 * mat0
mat3.move(fp.master_gear.Placement.Base)
fp.slave_gear.Placement = mat3
if isinstance(fp.master_gear.Proxy, CycloidGear) and isinstance(fp.slave_gear.Proxy, CycloidGear):
angle_master = fp.master_gear.Placement.Rotation.Angle * sum(fp.master_gear.Placement.Rotation.Axis)
dw_master = fp.master_gear.dw
dw_slave = fp.slave_gear.dw
dist = (dw_master + dw_slave) / 2
mat0 = FreeCAD.Matrix() # unity matrix
trans = FreeCAD.Vector(dist, 0, 0)
mat0.move(trans)
rot = FreeCAD.Rotation(FreeCAD.Vector(0,0,1), fp.angle1).toMatrix()
angle2 = dw_master / dw_slave * fp.angle1.Value
angle4 = dw_master / dw_slave * np.rad2deg(angle_master)
rot2 = FreeCAD.Rotation(FreeCAD.Vector(0,0,1), angle2).toMatrix()
angle3 = abs(fp.slave_gear.teeth % 2 - 1) * 180. / fp.slave_gear.teeth
rot3 = FreeCAD.Rotation(FreeCAD.Vector(0,0,1), angle3).toMatrix()
rot4 = FreeCAD.Rotation(FreeCAD.Vector(0,0,1), -angle4).toMatrix()
mat1 = rot * mat0 * rot2 * rot3 * rot4
mat1.move(fp.master_gear.Placement.Base)
fp.slave_gear.Placement = mat1
def execute(self, fp):
self.onChanged(fp, None)

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 21 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 18 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -1,18 +1,21 @@
# -*- 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 free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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. *
# * 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 Library 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/>. *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
@@ -37,35 +40,29 @@ class GearWorkbench(Workbench):
Icon = os.path.join(__dirname__, 'icons', 'gearworkbench.svg')
commands = [
"CreateInvoluteGear",
"CreateInternalInvoluteGear",
"CreateInvoluteRack",
"CreateCycloidGear",
"CreateCycloidRack",
"CreateBevelGear",
"CreateCrownGear",
"CreateWormGear",
"CreateTimingGear",
"CreateLanternGear",
"CreateHypoCycloidGear",
"CreateGearConnector"]
"CreateHypoCycloidGear"]
def GetClassName(self):
return "Gui::PythonWorkbench"
def Initialize(self):
from .commands import CreateCycloidGear, CreateInvoluteGear, CreateInternalInvoluteGear
from .commands import CreateCycloidGear, CreateInvoluteGear
from .commands import CreateBevelGear, CreateInvoluteRack, CreateCrownGear
from .commands import CreateWormGear, CreateTimingGear, CreateLanternGear
from .commands import CreateHypoCycloidGear, CreateCycloidRack
from .commands import CreateGearConnector
from .commands import CreateHypoCycloidGear
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())
Gui.addCommand('CreateCycloidRack', CreateCycloidRack())
Gui.addCommand('CreateBevelGear', CreateBevelGear())
Gui.addCommand('CreateInvoluteRack', CreateInvoluteRack())
Gui.addCommand('CreateCrownGear', CreateCrownGear())
@@ -73,7 +70,6 @@ class GearWorkbench(Workbench):
Gui.addCommand('CreateTimingGear', CreateTimingGear())
Gui.addCommand('CreateLanternGear', CreateLanternGear())
Gui.addCommand('CreateHypoCycloidGear', CreateHypoCycloidGear())
Gui.addCommand('CreateGearConnector', CreateGearConnector())
def Activated(self):
pass

View File

@@ -6,6 +6,7 @@
<date>2022-02-07</date>
<maintainer email="sppedflyer@gmail.com">looooo</maintainer>
<license file="LICENSE">GPL 3</license>
<dep>scipy</dep>
<url type="repository" branch="develop">https://github.com/looooo/freecad.gears</url>
<url type="bugtracker">https://github.com/looooo/freecad.gears/issues</url>
<url type="documentation">https://wiki.freecad.org/FCGear_Workbench</url>
@@ -21,4 +22,4 @@
</workbench>
</content>
</package>
</package>

View File

@@ -1,19 +1,22 @@
# -*- 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 free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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. *
# * 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 Library 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/>. *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
__version__ = "0.0.4"
__version__ = "0.0.3"

View File

@@ -1,18 +1,21 @@
# -*- 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 free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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. *
# * 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 Library 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/>. *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************

View File

@@ -1,18 +1,21 @@
# -*- 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 free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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. *
# * 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 Library 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/>. *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
@@ -30,7 +33,6 @@ class BevelTooth(object):
self.z = z
self.clearance = clearance
self.backlash = backlash
self.angular_backlash = backlash / (z * module / 2)
self.module = module
self.involute_end = arccos(
@@ -109,7 +111,7 @@ class BevelTooth(object):
intersection_point = intersection_line_circle(xy[i], point, r_cut)
xy = array([intersection_point] + list(xy[i+1:]))
xyz = [[p[0], p[1], 1] for p in xy]
backlash_rot = rotation3D(self.angular_backlash / 2)
backlash_rot = rotation3D(self.backlash / 4)
xyz = backlash_rot(xyz)
return(xyz)

View File

@@ -1,22 +1,26 @@
# -*- 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 free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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. *
# * 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 Library 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/>. *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
import numpy as np
from scipy import optimize as opt
def compute_shifted_gears(m, alpha, t1, t2, x1, x2):
@@ -33,32 +37,10 @@ def compute_shifted_gears(m, alpha, t1, t2, x1, x2):
Returns:
(float, float): distance between gears [length], pressure angle of the assembly [rad]
"""
def inv(x):
return np.tan(x) - x
def inv(x): return np.tan(x) - x
inv_alpha_w = inv(alpha) + 2 * np.tan(alpha) * (x1 + x2) / (t1 + t2)
def root_inv(x):
return inv(x) - inv_alpha_w
def d_root_inv(x):
return 1. / np.cos(x) - 1
alpha_w = find_root(alpha, root_inv, d_root_inv)
def root_inv(x): return inv(x) - inv_alpha_w
alpha_w = opt.fsolve(root_inv, 0.)
dist = m * (t1 + t2) / 2 * np.cos(alpha) / np.cos(alpha_w)
return dist, alpha_w
def find_root(x0, f, df, epsilon=2e-10, max_iter=100):
x_n = x0
for i in range(max_iter):
f_xn = f(x_n)
if abs(f_xn) < epsilon:
return x_n
else:
df_xn = df(x_n)
if df_xn == 0:
return None
else:
x_n = x_n - f_xn / df_xn / 2 # adding (/ 2) to avoid oscillation
return None

View File

@@ -1,18 +1,21 @@
# -*- 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 free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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. *
# * 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 Library 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/>. *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
@@ -22,14 +25,14 @@ from ._functions import rotation, reflection
class CycloidTooth():
def __init__(self, z1=5, z2=5, z=14, m=5, clearance=0.25, backlash=0.00, head=0.0):
def __init__(self, z1=5, z2=5, z=14, m=5, clearance=0.12, backlash=0.00, head=0.0):
self.m = m
self.z = z
self.clearance = clearance
self.head = head
self.backlash = backlash
self.z1 = z1
self.z2 = z2
self.head = head
self._calc_gear_factors()
def _calc_gear_factors(self):
@@ -37,10 +40,9 @@ class CycloidTooth():
self.d2 = self.z2 * self.m
self.phi = self.m * pi
self.d = self.z * self.m
self.da = self.d + 2 * (1 + self.head) * self.m
self.di = self.d - 2 * (1 + self.clearance) * self.m
self.da = self.d + 2*self.m + self.head * self.m
self.di = self.d - 2*self.m - self.clearance * self.m
self.phipart = 2 * pi / self.z
self.angular_backlash = self.backlash / (self.d / 2)
def epicycloid_x(self):
def func(t):
@@ -93,7 +95,7 @@ class CycloidTooth():
pts_outer = transpose([pts_outer_x, pts_outer_y])
pts_inner = transpose([pts_inner_x, pts_inner_y])
pts1 = vstack([pts_inner[:-2], pts_outer])
rot = rotation(self.phipart / 4 - self.angular_backlash / 2)
rot = rotation(self.phipart / 4 - self.backlash)
pts1 = rot(pts1)
ref = reflection(0.)
pts2 = ref(pts1)[::-1]

View File

@@ -1,18 +1,21 @@
# -*- 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 free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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. *
# * 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 Library 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/>. *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
@@ -69,7 +72,6 @@ class InvoluteTooth():
self.involute_rot2 = 1 / self.z * \
(pi / 2 + 2 * self.shift * tan(self.pressure_angle_t))
self.involute_rot = self.involute_rot1 + self.involute_rot2
self.angular_backlash = self.backlash / (self.d / 2)
self.involute_start = 0.
if self.dg <= self.df:
self.involute_start = sqrt(self.df ** 2 - self.dg ** 2) / self.dg
@@ -82,7 +84,7 @@ class InvoluteTooth():
y = array(list(map(fy, pts)))
xy = transpose([x, y])
rotate = rotation(
self.undercut_rot + self.phipart / 2 - self.angular_backlash / 2)
self.undercut_rot + self.phipart / 2 - self.backlash / 4)
xy = rotate(xy)
return(array(xy))
@@ -92,7 +94,7 @@ class InvoluteTooth():
x = array(list(map(fx, pts)))
fy = self.involute_function_y()
y = array(list(map(fy, pts)))
rot = rotation(self.involute_rot - self.angular_backlash / 2)
rot = rotation(self.involute_rot - self.backlash / 4)
xy = rot(transpose(array([x, y])))
return(xy)