home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / libgimp / gimpvector.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-06  |  9.5 KB  |  404 lines

  1. /* LIBGIMP - The GIMP Library
  2.  * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
  3.  *
  4.  * The gimp_vector* functions were taken from:
  5.  * GCK - The General Convenience Kit
  6.  * Copyright (C) 1996 Tom Bech
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Lesser General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Lesser General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Lesser General Public
  19.  * License along with this library; if not, write to the
  20.  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  21.  * Boston, MA 02111-1307, USA.
  22.  */
  23.  
  24. /**********************************************/
  25. /* A little collection of useful vector stuff */
  26. /**********************************************/
  27.  
  28. #include <glib.h>
  29.  
  30. #include "gimpmath.h"
  31. #include "gimpvector.h"
  32.  
  33.  
  34. /*************************/
  35. /* Some useful constants */
  36. /*************************/
  37.  
  38. static const GimpVector2 gimp_vector2_zero =   { 0.0, 0.0 };
  39. static const GimpVector2 gimp_vector2_unit_x = { 1.0, 0.0 };
  40. static const GimpVector2 gimp_vector2_unit_y = { 0.0, 1.0 };
  41.  
  42. static const GimpVector3 gimp_vector3_zero =   { 0.0, 0.0, 0.0 };
  43. static const GimpVector3 gimp_vector3_unit_x = { 1.0, 0.0, 0.0 };
  44. static const GimpVector3 gimp_vector3_unit_y = { 0.0, 1.0, 0.0 };
  45. static const GimpVector3 gimp_vector3_unit_z = { 0.0, 0.0, 1.0 };
  46.  
  47. /**************************************/
  48. /* Three dimensional vector functions */
  49. /**************************************/
  50.  
  51. gdouble
  52. gimp_vector2_inner_product (GimpVector2 *vector1,
  53.                 GimpVector2 *vector2)
  54. {
  55.   g_assert (vector1 != NULL);
  56.   g_assert (vector2 != NULL);
  57.  
  58.   return (vector1->x * vector2->x + vector1->y * vector2->y);
  59. }
  60.  
  61. GimpVector2
  62. gimp_vector2_cross_product (GimpVector2 *vector1,
  63.                 GimpVector2 *vector2)
  64. {
  65.   GimpVector2 normal;
  66.  
  67.   g_assert (vector1 != NULL);
  68.   g_assert (vector2 != NULL);
  69.  
  70.   normal.x = vector1->x * vector2->y - vector1->y * vector2->x;
  71.   normal.y = vector1->y * vector2->x - vector1->x * vector2->y;
  72.  
  73.   return normal;
  74. }
  75.  
  76. gdouble
  77. gimp_vector2_length (GimpVector2 *vector)
  78. {
  79.   g_assert (vector != NULL);
  80.  
  81.   return (sqrt (vector->x * vector->x + vector->y * vector->y));
  82. }
  83.  
  84. void
  85. gimp_vector2_normalize (GimpVector2 *vector)
  86. {
  87.   gdouble len;
  88.  
  89.   g_assert (vector != NULL);
  90.  
  91.   len = gimp_vector2_length (vector);
  92.   if (len != 0.0) 
  93.     {
  94.       len = 1.0 / len;
  95.       vector->x *= len;
  96.       vector->y *= len;
  97.     }
  98.   else
  99.     {
  100.       *vector = gimp_vector2_zero;
  101.     }
  102. }
  103.  
  104. void
  105. gimp_vector2_mul (GimpVector2 *vector,
  106.           gdouble      factor)
  107. {
  108.   g_assert (vector != NULL);
  109.  
  110.   vector->x *= factor;
  111.   vector->y *= factor;
  112. }
  113.  
  114. void
  115. gimp_vector2_sub (GimpVector2 *result,
  116.           GimpVector2 *vector1,
  117.           GimpVector2 *vector2)
  118. {
  119.   g_assert (vector1 != NULL);
  120.   g_assert (vector2 != NULL);
  121.   g_assert (result != NULL);
  122.  
  123.   result->x = vector1->x - vector2->x;
  124.   result->y = vector1->y - vector2->y;
  125. }
  126.  
  127. void
  128. gimp_vector2_set (GimpVector2 *vector,
  129.           gdouble      x,
  130.           gdouble      y)
  131. {
  132.   g_assert (vector != NULL);
  133.  
  134.   vector->x = x;
  135.   vector->y = y;
  136. }
  137.  
  138. void
  139. gimp_vector2_add (GimpVector2 *result,
  140.           GimpVector2 *vector1,
  141.           GimpVector2 *vector2)
  142. {
  143.   g_assert (vector1 != NULL);
  144.   g_assert (vector2 != NULL);
  145.   g_assert (result != NULL);
  146.  
  147.   result->x = vector1->x + vector2->x;
  148.   result->y = vector1->y + vector2->y;
  149. }
  150.  
  151. void
  152. gimp_vector2_neg (GimpVector2 *vector)
  153. {
  154.   g_assert (vector != NULL);
  155.  
  156.   vector->x *= -1.0;
  157.   vector->y *= -1.0;
  158. }
  159.  
  160. void
  161. gimp_vector2_rotate (GimpVector2 *vector,
  162.              gdouble      alpha)
  163. {
  164.   GimpVector2 result;
  165.  
  166.   g_assert (vector != NULL);
  167.  
  168.   result.x = cos (alpha) * vector->x + sin (alpha) * vector->y;
  169.   result.y = cos (alpha) * vector->y - sin (alpha) * vector->x;
  170.  
  171.   *vector = result;
  172. }
  173.  
  174. /**************************************/
  175. /* Three dimensional vector functions */
  176. /**************************************/
  177.  
  178. gdouble
  179. gimp_vector3_inner_product (GimpVector3 *vector1,
  180.                 GimpVector3 *vector2)
  181. {
  182.   g_assert (vector1 != NULL);
  183.   g_assert (vector2 != NULL);
  184.  
  185.   return (vector1->x * vector2->x +
  186.       vector1->y * vector2->y +
  187.       vector1->z * vector2->z);
  188. }
  189.  
  190. GimpVector3
  191. gimp_vector3_cross_product (GimpVector3 *vector1,
  192.                 GimpVector3 *vector2)
  193. {
  194.   GimpVector3 normal;
  195.  
  196.   g_assert (vector1 != NULL);
  197.   g_assert (vector2 != NULL);
  198.  
  199.   normal.x = vector1->y * vector2->z - vector1->z * vector2->y;
  200.   normal.y = vector1->z * vector2->x - vector1->x * vector2->z;
  201.   normal.z = vector1->x * vector2->y - vector1->y * vector2->x;
  202.  
  203.   return normal;
  204. }
  205.  
  206. gdouble
  207. gimp_vector3_length (GimpVector3 *vector)
  208. {
  209.   g_assert (vector != NULL);
  210.  
  211.   return (sqrt (vector->x * vector->x +
  212.         vector->y * vector->y +
  213.         vector->z * vector->z));
  214. }
  215.  
  216. void
  217. gimp_vector3_normalize (GimpVector3 *vector)
  218. {
  219.   gdouble len;
  220.  
  221.   g_assert (vector != NULL);
  222.  
  223.   len = gimp_vector3_length (vector);
  224.   if (len != 0.0)
  225.     {
  226.       len = 1.0 / len;
  227.       vector->x *= len;
  228.       vector->y *= len;
  229.       vector->z *= len;
  230.     }
  231.   else
  232.     {
  233.       *vector = gimp_vector3_zero;
  234.     }
  235. }
  236.  
  237. void
  238. gimp_vector3_mul (GimpVector3 *vector,
  239.           gdouble      factor)
  240. {
  241.   g_assert (vector != NULL);
  242.  
  243.   vector->x *= factor;
  244.   vector->y *= factor;
  245.   vector->z *= factor;
  246. }
  247.  
  248. void
  249. gimp_vector3_sub (GimpVector3 *result,
  250.           GimpVector3 *vector1,
  251.           GimpVector3 *vector2)
  252. {
  253.   g_assert (vector1 != NULL);
  254.   g_assert (vector2 != NULL);
  255.   g_assert (result != NULL);
  256.  
  257.   result->x = vector1->x - vector2->x;
  258.   result->y = vector1->y - vector2->y;
  259.   result->z = vector1->z - vector2->z;
  260. }
  261.  
  262. void
  263. gimp_vector3_set (GimpVector3 *vector,
  264.           gdouble      x,
  265.           gdouble      y,
  266.           gdouble      z)
  267. {
  268.   g_assert (vector != NULL);
  269.  
  270.   vector->x = x;
  271.   vector->y = y;
  272.   vector->z = z;
  273. }
  274.  
  275. void
  276. gimp_vector3_add (GimpVector3 *result,
  277.           GimpVector3 *vector1,
  278.           GimpVector3 *vector2)
  279. {
  280.   g_assert (vector1 != NULL);
  281.   g_assert (vector2 != NULL);
  282.   g_assert (result != NULL);
  283.  
  284.   result->x = vector1->x + vector2->x;
  285.   result->y = vector1->y + vector2->y;
  286.   result->z = vector1->z + vector2->z;
  287. }
  288.  
  289. void
  290. gimp_vector3_neg (GimpVector3 *vector)
  291. {
  292.   g_assert (vector != NULL);
  293.  
  294.   vector->x *= -1.0;
  295.   vector->y *= -1.0;
  296.   vector->z *= -1.0;
  297. }
  298.  
  299. void
  300. gimp_vector3_rotate (GimpVector3 *vector,
  301.              gdouble      alpha,
  302.              gdouble      beta,
  303.              gdouble      gamma)
  304. {
  305.   GimpVector3 s, t;
  306.  
  307.   g_assert (vector != NULL);
  308.  
  309.   /* First we rotate it around the Z axis (XY plane).. */
  310.   /* ================================================= */
  311.  
  312.   s.x = cos (alpha) * vector->x + sin (alpha) * vector->y;
  313.   s.y = cos (alpha) * vector->y - sin (alpha) * vector->x;
  314.  
  315.   /* ..then around the Y axis (XZ plane).. */
  316.   /* ===================================== */
  317.  
  318.   t = s;
  319.  
  320.   vector->x = cos (beta) *t.x       + sin (beta) * vector->z;
  321.   s.z       = cos (beta) *vector->z - sin (beta) * t.x;
  322.  
  323.   /* ..and at last around the X axis (YZ plane) */
  324.   /* ========================================== */
  325.  
  326.   vector->y = cos (gamma) * t.y + sin (gamma) * s.z;
  327.   vector->z = cos (gamma) * s.z - sin (gamma) * t.y;
  328. }
  329.  
  330. /******************************************************************/
  331. /* Compute screen (sx,sy)-(sx+w,sy+h) to 3D unit square mapping.  */
  332. /* The plane to map to is given in the z field of p. The observer */
  333. /* is located at position vp (vp->z!=0.0).                        */
  334. /******************************************************************/
  335.  
  336. void
  337. gimp_vector_2d_to_3d (gint         sx,
  338.               gint         sy,
  339.               gint         w,
  340.               gint         h,
  341.               gint         x,
  342.               gint         y,
  343.               GimpVector3 *vp,
  344.               GimpVector3 *p)
  345. {
  346.   gdouble t = 0.0;
  347.  
  348.   g_assert (vp != NULL);
  349.   g_assert (p != NULL);
  350.  
  351.   if (vp->x != 0.0)
  352.     t = (p->z - vp->z) / vp->z;
  353.  
  354.   if (t != 0.0)
  355.     {
  356.       p->x = vp->x + t * (vp->x - ((gdouble) (x - sx) / (gdouble) w));
  357.       p->y = vp->y + t * (vp->y - ((gdouble) (y - sy) / (gdouble) h));
  358.     }
  359.   else
  360.     {
  361.       p->x = (gdouble) (x - sx) / (gdouble) w;
  362.       p->y = (gdouble) (y - sy) / (gdouble) h;     
  363.     }
  364. }
  365.  
  366. /*********************************************************/
  367. /* Convert the given 3D point to 2D (project it onto the */
  368. /* viewing plane, (sx,sy,0)-(sx+w,sy+h,0). The input is  */
  369. /* assumed to be in the unit square (0,0,z)-(1,1,z).     */
  370. /* The viewpoint of the observer is passed in vp.        */
  371. /*********************************************************/
  372.  
  373. void
  374. gimp_vector_3d_to_2d (gint         sx,
  375.               gint         sy,
  376.               gint         w,
  377.               gint         h,
  378.               gdouble     *x,
  379.               gdouble     *y,
  380.               GimpVector3 *vp,
  381.               GimpVector3 *p)
  382. {
  383.   gdouble t;
  384.   GimpVector3 dir;
  385.  
  386.   g_assert (vp != NULL);
  387.   g_assert (p != NULL);
  388.  
  389.   gimp_vector3_sub (&dir, p, vp);
  390.   gimp_vector3_normalize (&dir);
  391.  
  392.   if (dir.z != 0.0)
  393.     {
  394.       t = (-1.0 * vp->z) / dir.z;
  395.       *x = (gdouble) sx + ((vp->x + t * dir.x) * (gdouble) w);
  396.       *y = (gdouble) sy + ((vp->y + t * dir.y) * (gdouble) h);
  397.     }
  398.   else
  399.     {
  400.       *x = (gdouble) sx + (p->x * (gdouble) w);
  401.       *y = (gdouble) sy + (p->y * (gdouble) h);
  402.     }
  403. }
  404.