Returns the derivative of sp_spiral_get_xy with respect to t, scaled to a unit vector.
Definition at line 569 of file spspiral.cpp. References SPSpiral::arg, Geom::dot(), SPSpiral::exp, Geom::L2(), Geom::Point::normalize(), and SPSpiral::revo. Referenced by sp_spiral_fit_and_draw(). { Geom::Point ret(1.0, 0.0); g_return_val_if_fail (( ( spiral != NULL ) && SP_IS_SPIRAL(spiral) ), ret); g_assert (t >= 0.0); g_assert (spiral>exp >= 0.0); /* See above for comments on these assertions. */ double const t_scaled = 2.0 * M_PI * spiral>revo * t; double const arg = t_scaled + spiral>arg; double const s = sin (arg); double const c = cos (arg); if (spiral>exp == 0.0) { ret = Geom::Point(s, c); } else if (t_scaled == 0.0) { ret = Geom::Point(c, s); } else { Geom::Point unrotated(spiral>exp, t_scaled); double const s_len = L2 (unrotated); g_assert (s_len != 0); /** \todo * Check that this isn't being too hopeful of the hypot * function. E.g. test with numbers around 2**1070 * (denormalized numbers), preferably on a few different * platforms. However, njh says that the usual implementation * does handle both very big and very small numbers. */ unrotated /= s_len; /* ret = spiral>exp * (c, s) + t_scaled * (s, c); alternatively ret = (spiral>exp, t_scaled) * (( c, s), (s, c)).*/ ret = Geom::Point(dot(unrotated, Geom::Point(c, s)), dot(unrotated, Geom::Point(s, c))); /* ret should already be approximately normalized: the matrix ((c, s), (s, c)) is orthogonal (it just rotates by arg), and unrotated has been normalized, so ret is already of unit length other than numerical error in the above matrix multiplication. */ /** \todo * I haven't checked how important it is for ret to be very * near unit length; we could get rid of the below. */ ret.normalize(); /* Proof that ret length is nonzero: see above. (Should be near 1.) */ } g_assert (is_unit_vector (ret)); return ret; }
