13#include <glibmm/i18n.h>
21 double pitch_diameter() {
return (_number_of_teeth * _module) / M_PI;}
22 double pitch_radius() {
return pitch_diameter() / 2.0;}
23 void pitch_radius(
double R) {_module = (2 * M_PI *
R) / _number_of_teeth;}
26 double base_diameter() {
return pitch_diameter() *
cos(_pressure_angle);}
27 double base_radius() {
return base_diameter() / 2.0;}
30 double diametrical_pitch() {
return _number_of_teeth / pitch_diameter();}
33 double addendum() {
return 1.0 / diametrical_pitch();}
35 double dedendum() {
return addendum() + _clearance;}
38 double root_radius() {
return pitch_radius() - dedendum();}
39 double root_diameter() {
return root_radius() * 2.0;}
42 double outer_radius() {
return pitch_radius() + addendum();}
43 double outer_diameter() {
return outer_radius() * 2.0;}
46 double tooth_thickness_angle() {
return M_PI / _number_of_teeth;}
51 double angle() {
return _angle;}
52 void angle(
double a) {_angle = a;}
54 int number_of_teeth() {
return _number_of_teeth;}
59 Gear(
int n,
double m,
double phi)
61 , _pressure_angle(phi)
67 double _pressure_angle;
69 double _clearance = 0.0;
81 I =
I*base_radius() + _centre;
95 double involute_swath_angle(
double R) {
96 if (
R <= base_radius())
return 0.0;
97 return sqrt(
R*
R - base_radius()*base_radius())/base_radius();
101 double involute_intersect_angle(
double R) {
102 if (
R <= base_radius())
return 0.0;
103 return (
sqrt(
R*
R - base_radius()*base_radius())/base_radius()) - acos(base_radius()/
R);
109 for(
unsigned d=0;d<2;d++)
117 double tooth_rotation = 2.0 * tooth_thickness_angle();
119 double involute_advance = involute_intersect_angle(outer_radius()) - involute_intersect_angle(root_radius());
121 double tip_advance = tooth_thickness_angle() - (2 * (involute_intersect_angle(outer_radius()) - involute_intersect_angle(pitch_radius())));
123 double root_advance = (tooth_rotation - tip_advance) - (2.0 * involute_advance);
125 double involute_t = involute_swath_angle(root_radius())/involute_swath_angle(outer_radius());
128 double first_tooth_angle = _angle - ((0.5 * tip_advance) + involute_advance);
131 for (
int i=0; i < _number_of_teeth; i++)
133 double cursor = first_tooth_angle + (i * tooth_rotation);
135 D2<SBasis> leading_I =
compose(_involute(cursor, cursor + involute_swath_angle(outer_radius())),
Linear(involute_t,1));
138 cursor += involute_advance;
139 prev = leading_I.at1();
141 D2<SBasis> tip = _arc(cursor, cursor+tip_advance, outer_radius());
144 cursor += tip_advance;
147 cursor += involute_advance;
148 D2<SBasis> trailing_I =
compose(_involute(cursor, cursor - involute_swath_angle(outer_radius())),
Linear(1,involute_t));
151 prev = trailing_I.
at1();
153 if (base_radius() > root_radius()) {
160 D2<SBasis> root = _arc(cursor, cursor+root_advance, root_radius());
166 if (base_radius() > root_radius()) {
178 double radius =
Geom::distance(this->centre(), p) - this->pitch_radius();
179 int N = (int)
floor( (radius / this->pitch_radius()) * this->number_of_teeth() );
181 Gear gear(
N, _module, _pressure_angle);
184 double a =
atan2(p - this->centre());
185 double new_angle = 0.0;
186 if (gear.number_of_teeth() % 2 == 0)
187 new_angle -= gear.tooth_thickness_angle();
188 new_angle -= (_angle) * (pitch_radius() / gear.pitch_radius());
189 new_angle += (a) * (pitch_radius() / gear.pitch_radius());
190 gear.angle(new_angle + a);
201namespace LivePathEffect {
206 teeth(_(
"_Teeth:"), _(
"The number of teeth"),
"teeth", &wr, this, 10),
207 phi(_(
"_Phi:"), _(
"Tooth pressure angle (typically 20-25 deg). The ratio of teeth not in contact."),
"phi", &wr, this, 5),
208 min_radius(_(
"Min Radius:"), _(
"Minimum radius, low values can be slow"),
"min_radius", &wr, this, 5.0)
234 if ( it == gearpath.
end() )
return path_out;
236 Gear * gear =
new Gear(
teeth, 200.0,
phi * M_PI / 180);
238 gear->centre(gear_centre);
239 gear->angle(
atan2((*it).initialPoint() - gear_centre));
242 if ( it == gearpath.
end() )
return path_out;
245 gear->pitch_radius(radius);
249 for (++it; it != gearpath.
end() ; ++it) {
250 if (
are_near((*it).initialPoint(), (*it).finalPoint())) {
254 Gear* gearnew =
new Gear(gear->spawn( (*it).finalPoint() ));
Conversion between Bezier control points and SBasis curves.
Adaptor that creates 2D functions from 1D ones.
Function that interpolates linearly between two values.
void push_back(Path const &path)
Append a path at the end.
Sequence of contiguous curves, aka spline.
const_iterator end() const
void append(Curve *curve)
Add a new curve to the end of the path.
const_iterator begin() const
void appendNew(Args &&... args)
Append a new curve to the path.
Two-dimensional point that doubles as a vector.
Symmetric power basis curve.
void registerParameter(Parameter *param)
LPEGears(LivePathEffectObject *lpeobject)
Geom::PathVector doEffect_path(Geom::PathVector const &path_in) override
void param_set_range(double min, double max)
void param_make_integer(bool yes=true)
auto floor(Geom::Rect const &rect)
static void makeContinuous(D2< SBasis > &a, Point const b)
double angle(std::vector< Point > const &A)
Various utility functions.
SBasisN< n > cos(LinearN< n > bo, int k)
Angle distance(Angle const &a, Angle const &b)
double atan2(Point const &p)
SBasisN< n > sqrt(SBasisN< n > const &a, int k)
D2< T > compose(D2< T > const &a, T const &b)
Bezier derivative(Bezier const &a)
Point unit_vector(Point const &a)
SBasisN< n > sin(LinearN< n > bo, int k)
bool are_near(Affine const &a1, Affine const &a2, Coord eps=EPSILON)
Helper class to stream background task notifications as a series of messages.