Logo Search packages:      
Sourcecode: inkscape version File versions

static Geom::Point sp_spiral_get_tangent ( SPSpiral const *  spiral,
gdouble  t 
) [static]

Returns the derivative of sp_spiral_get_xy with respect to t, scaled to a unit vector.

Precondition:
spiral != 0.

0 <= t.

p != NULL.

Postcondition:
is_unit_vector(*p).

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.

Todo:
I haven't checked how important it is for ret to be very near unit length; we could get rid of the below.

Definition at line 569 of file sp-spiral.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 non-zero: see above.  (Should be near 1.) */
      }

      g_assert (is_unit_vector (ret));
      return ret;
}


Generated by  Doxygen 1.6.0   Back to index