Logo Search packages:      
Sourcecode: inkscape version File versions

static NR::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).

Definition at line 468 of file sp-spiral.cpp.

Referenced by sp_spiral_fit_and_draw().

{
      NR::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 = NR::Point(-s, c);
      } else if (t_scaled == 0.0) {
            ret = NR::Point(c, s);
      } else {
            NR::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 = NR::Point(dot(unrotated, NR::Point(c, -s)),
                        dot(unrotated, NR::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.

               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