summaryrefslogtreecommitdiffstats
path: root/libgimpmath/gimpvector.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--libgimpmath/gimpvector.c1129
1 files changed, 1129 insertions, 0 deletions
diff --git a/libgimpmath/gimpvector.c b/libgimpmath/gimpvector.c
new file mode 100644
index 0000000..5f2b174
--- /dev/null
+++ b/libgimpmath/gimpvector.c
@@ -0,0 +1,1129 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * gimpvector.c
+ *
+ * The gimp_vector* functions were taken from:
+ * GCK - The General Convenience Kit
+ * Copyright (C) 1996 Tom Bech
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+/**********************************************/
+/* A little collection of useful vector stuff */
+/**********************************************/
+
+#include "config.h"
+
+#include <glib-object.h>
+
+#include "gimpmath.h"
+
+
+/**
+ * SECTION: gimpvector
+ * @title: GimpVector
+ * @short_description: Utilities to set up and manipulate vectors.
+ * @see_also: #GimpMatrix2, #GimpMatrix3, #GimpMatrix4
+ *
+ * Utilities to set up and manipulate vectors.
+ **/
+
+
+/*************************/
+/* Some useful constants */
+/*************************/
+
+static const GimpVector2 gimp_vector2_zero = { 0.0, 0.0 };
+#if 0
+static const GimpVector2 gimp_vector2_unit_x = { 1.0, 0.0 };
+static const GimpVector2 gimp_vector2_unit_y = { 0.0, 1.0 };
+#endif
+
+static const GimpVector3 gimp_vector3_zero = { 0.0, 0.0, 0.0 };
+#if 0
+static const GimpVector3 gimp_vector3_unit_x = { 1.0, 0.0, 0.0 };
+static const GimpVector3 gimp_vector3_unit_y = { 0.0, 1.0, 0.0 };
+static const GimpVector3 gimp_vector3_unit_z = { 0.0, 0.0, 1.0 };
+#endif
+
+/**************************************/
+/* Two dimensional vector functions */
+/**************************************/
+
+/**
+ * gimp_vector2_new:
+ * @x: the X coordinate.
+ * @y: the Y coordinate.
+ *
+ * Creates a #GimpVector2 of coordinates @x and @y.
+ *
+ * Returns: the resulting #GimpVector2.
+ **/
+GimpVector2
+gimp_vector2_new (gdouble x,
+ gdouble y)
+{
+ GimpVector2 vector;
+
+ vector.x = x;
+ vector.y = y;
+
+ return vector;
+}
+
+/**
+ * gimp_vector2_set:
+ * @vector: a pointer to a #GimpVector2.
+ * @x: the X coordinate.
+ * @y: the Y coordinate.
+ *
+ * Sets the X and Y coordinates of @vector to @x and @y.
+ **/
+void
+gimp_vector2_set (GimpVector2 *vector,
+ gdouble x,
+ gdouble y)
+{
+ vector->x = x;
+ vector->y = y;
+}
+
+/**
+ * gimp_vector2_length:
+ * @vector: a pointer to a #GimpVector2.
+ *
+ * Computes the length of a 2D vector.
+ *
+ * Returns: the length of @vector (a positive gdouble).
+ **/
+gdouble
+gimp_vector2_length (const GimpVector2 *vector)
+{
+ return (sqrt (vector->x * vector->x + vector->y * vector->y));
+}
+
+/**
+ * gimp_vector2_length_val:
+ * @vector: a #GimpVector2.
+ *
+ * This function is identical to gimp_vector2_length() but the
+ * vector is passed by value rather than by reference.
+ *
+ * Returns: the length of @vector (a positive gdouble).
+ **/
+gdouble
+gimp_vector2_length_val (GimpVector2 vector)
+{
+ return (sqrt (vector.x * vector.x + vector.y * vector.y));
+}
+
+/**
+ * gimp_vector2_mul:
+ * @vector: a pointer to a #GimpVector2.
+ * @factor: a scalar.
+ *
+ * Multiplies each component of the @vector by @factor. Note that this
+ * is equivalent to multiplying the vectors length by @factor.
+ **/
+void
+gimp_vector2_mul (GimpVector2 *vector,
+ gdouble factor)
+{
+ vector->x *= factor;
+ vector->y *= factor;
+}
+
+/**
+ * gimp_vector2_mul_val:
+ * @vector: a #GimpVector2.
+ * @factor: a scalar.
+ *
+ * This function is identical to gimp_vector2_mul() but the vector is
+ * passed by value rather than by reference.
+ *
+ * Returns: the resulting #GimpVector2.
+ **/
+GimpVector2
+gimp_vector2_mul_val (GimpVector2 vector,
+ gdouble factor)
+{
+ GimpVector2 result;
+
+ result.x = vector.x * factor;
+ result.y = vector.y * factor;
+
+ return result;
+}
+
+
+/**
+ * gimp_vector2_normalize:
+ * @vector: a pointer to a #GimpVector2.
+ *
+ * Normalizes the @vector so the length of the @vector is 1.0. The nul
+ * vector will not be changed.
+ **/
+void
+gimp_vector2_normalize (GimpVector2 *vector)
+{
+ gdouble len;
+
+ len = gimp_vector2_length (vector);
+
+ if (len != 0.0)
+ {
+ len = 1.0 / len;
+ vector->x *= len;
+ vector->y *= len;
+ }
+ else
+ {
+ *vector = gimp_vector2_zero;
+ }
+}
+
+/**
+ * gimp_vector2_normalize_val:
+ * @vector: a #GimpVector2.
+ *
+ * This function is identical to gimp_vector2_normalize() but the
+ * vector is passed by value rather than by reference.
+ *
+ * Returns: a #GimpVector2 parallel to @vector, pointing in the same
+ * direction but with a length of 1.0.
+ **/
+GimpVector2
+gimp_vector2_normalize_val (GimpVector2 vector)
+{
+ GimpVector2 normalized;
+ gdouble len;
+
+ len = gimp_vector2_length_val (vector);
+
+ if (len != 0.0)
+ {
+ len = 1.0 / len;
+ normalized.x = vector.x * len;
+ normalized.y = vector.y * len;
+ return normalized;
+ }
+ else
+ {
+ return gimp_vector2_zero;
+ }
+}
+
+/**
+ * gimp_vector2_neg:
+ * @vector: a pointer to a #GimpVector2.
+ *
+ * Negates the @vector (i.e. negate all its coordinates).
+ **/
+void
+gimp_vector2_neg (GimpVector2 *vector)
+{
+ vector->x *= -1.0;
+ vector->y *= -1.0;
+}
+
+/**
+ * gimp_vector2_neg_val:
+ * @vector: a #GimpVector2.
+ *
+ * This function is identical to gimp_vector2_neg() but the vector
+ * is passed by value rather than by reference.
+ *
+ * Returns: the negated #GimpVector2.
+ **/
+GimpVector2
+gimp_vector2_neg_val (GimpVector2 vector)
+{
+ GimpVector2 result;
+
+ result.x = vector.x * -1.0;
+ result.y = vector.y * -1.0;
+
+ return result;
+}
+
+/**
+ * gimp_vector2_add:
+ * @result: destination for the resulting #GimpVector2.
+ * @vector1: a pointer to the first #GimpVector2.
+ * @vector2: a pointer to the second #GimpVector2.
+ *
+ * Computes the sum of two 2D vectors. The resulting #GimpVector2 is
+ * stored in @result.
+ **/
+void
+gimp_vector2_add (GimpVector2 *result,
+ const GimpVector2 *vector1,
+ const GimpVector2 *vector2)
+{
+ result->x = vector1->x + vector2->x;
+ result->y = vector1->y + vector2->y;
+}
+
+/**
+ * gimp_vector2_add_val:
+ * @vector1: the first #GimpVector2.
+ * @vector2: the second #GimpVector2.
+ *
+ * This function is identical to gimp_vector2_add() but the vectors
+ * are passed by value rather than by reference.
+ *
+ * Returns: the resulting #GimpVector2.
+ **/
+GimpVector2
+gimp_vector2_add_val (GimpVector2 vector1,
+ GimpVector2 vector2)
+{
+ GimpVector2 result;
+
+ result.x = vector1.x + vector2.x;
+ result.y = vector1.y + vector2.y;
+
+ return result;
+}
+
+/**
+ * gimp_vector2_sub:
+ * @result: the destination for the resulting #GimpVector2.
+ * @vector1: a pointer to the first #GimpVector2.
+ * @vector2: a pointer to the second #GimpVector2.
+ *
+ * Computes the difference of two 2D vectors (@vector1 minus @vector2).
+ * The resulting #GimpVector2 is stored in @result.
+ **/
+void
+gimp_vector2_sub (GimpVector2 *result,
+ const GimpVector2 *vector1,
+ const GimpVector2 *vector2)
+{
+ result->x = vector1->x - vector2->x;
+ result->y = vector1->y - vector2->y;
+}
+
+/**
+ * gimp_vector2_sub_val:
+ * @vector1: the first #GimpVector2.
+ * @vector2: the second #GimpVector2.
+ *
+ * This function is identical to gimp_vector2_sub() but the vectors
+ * are passed by value rather than by reference.
+ *
+ * Returns: the resulting #GimpVector2.
+ **/
+GimpVector2
+gimp_vector2_sub_val (GimpVector2 vector1,
+ GimpVector2 vector2)
+{
+ GimpVector2 result;
+
+ result.x = vector1.x - vector2.x;
+ result.y = vector1.y - vector2.y;
+
+ return result;
+}
+
+/**
+ * gimp_vector2_inner_product:
+ * @vector1: a pointer to the first #GimpVector2.
+ * @vector2: a pointer to the second #GimpVector2.
+ *
+ * Computes the inner (dot) product of two 2D vectors.
+ * This product is zero if and only if the two vectors are orthogonal.
+ *
+ * Returns: The inner product.
+ **/
+gdouble
+gimp_vector2_inner_product (const GimpVector2 *vector1,
+ const GimpVector2 *vector2)
+{
+ return (vector1->x * vector2->x + vector1->y * vector2->y);
+}
+
+/**
+ * gimp_vector2_inner_product_val:
+ * @vector1: the first #GimpVector2.
+ * @vector2: the second #GimpVector2.
+ *
+ * This function is identical to gimp_vector2_inner_product() but the
+ * vectors are passed by value rather than by reference.
+ *
+ * Returns: The inner product.
+ **/
+gdouble
+gimp_vector2_inner_product_val (GimpVector2 vector1,
+ GimpVector2 vector2)
+{
+ return (vector1.x * vector2.x + vector1.y * vector2.y);
+}
+
+/**
+ * gimp_vector2_cross_product:
+ * @vector1: a pointer to the first #GimpVector2.
+ * @vector2: a pointer to the second #GimpVector2.
+ *
+ * Compute the cross product of two vectors. The result is a
+ * #GimpVector2 which is orthogonal to both @vector1 and @vector2. If
+ * @vector1 and @vector2 are parallel, the result will be the nul
+ * vector.
+ *
+ * Note that in 2D, this function is useful to test if two vectors are
+ * parallel or not, or to compute the area spawned by two vectors.
+ *
+ * Returns: The cross product.
+ **/
+GimpVector2
+gimp_vector2_cross_product (const GimpVector2 *vector1,
+ const GimpVector2 *vector2)
+{
+ GimpVector2 normal;
+
+ normal.x = vector1->x * vector2->y - vector1->y * vector2->x;
+ normal.y = vector1->y * vector2->x - vector1->x * vector2->y;
+
+ return normal;
+}
+
+/**
+ * gimp_vector2_cross_product_val:
+ * @vector1: the first #GimpVector2.
+ * @vector2: the second #GimpVector2.
+ *
+ * This function is identical to gimp_vector2_cross_product() but the
+ * vectors are passed by value rather than by reference.
+ *
+ * Returns: The cross product.
+ **/
+GimpVector2
+gimp_vector2_cross_product_val (GimpVector2 vector1,
+ GimpVector2 vector2)
+{
+ GimpVector2 normal;
+
+ normal.x = vector1.x * vector2.y - vector1.y * vector2.x;
+ normal.y = vector1.y * vector2.x - vector1.x * vector2.y;
+
+ return normal;
+}
+
+/**
+ * gimp_vector2_rotate:
+ * @vector: a pointer to a #GimpVector2.
+ * @alpha: an angle (in radians).
+ *
+ * Rotates the @vector counterclockwise by @alpha radians.
+ **/
+void
+gimp_vector2_rotate (GimpVector2 *vector,
+ gdouble alpha)
+{
+ GimpVector2 result;
+
+ result.x = cos (alpha) * vector->x + sin (alpha) * vector->y;
+ result.y = cos (alpha) * vector->y - sin (alpha) * vector->x;
+
+ *vector = result;
+}
+
+/**
+ * gimp_vector2_rotate_val:
+ * @vector: a #GimpVector2.
+ * @alpha: an angle (in radians).
+ *
+ * This function is identical to gimp_vector2_rotate() but the vector
+ * is passed by value rather than by reference.
+ *
+ * Returns: a #GimpVector2 representing @vector rotated by @alpha
+ * radians.
+ **/
+GimpVector2
+gimp_vector2_rotate_val (GimpVector2 vector,
+ gdouble alpha)
+{
+ GimpVector2 result;
+
+ result.x = cos (alpha) * vector.x + sin (alpha) * vector.y;
+ result.y = cos (alpha) * vector.y - sin (alpha) * vector.x;
+
+ return result;
+}
+
+/**
+ * gimp_vector2_normal:
+ * @vector: a pointer to a #GimpVector2.
+ *
+ * Compute a normalized perpendicular vector to @vector
+ *
+ * Returns: a #GimpVector2 perpendicular to @vector, with a length of 1.0.
+ *
+ * Since: 2.8
+ **/
+GimpVector2
+gimp_vector2_normal (GimpVector2 *vector)
+{
+ GimpVector2 result;
+
+ result.x = - vector->y;
+ result.y = vector->x;
+
+ gimp_vector2_normalize (&result);
+
+ return result;
+}
+
+/**
+ * gimp_vector2_normal_val:
+ * @vector: a #GimpVector2.
+ *
+ * This function is identical to gimp_vector2_normal() but the vector
+ * is passed by value rather than by reference.
+ *
+ * Returns: a #GimpVector2 perpendicular to @vector, with a length of 1.0.
+ *
+ * Since: 2.8
+ **/
+GimpVector2
+gimp_vector2_normal_val (GimpVector2 vector)
+{
+ GimpVector2 result;
+
+ result.x = - vector.y;
+ result.y = vector.x;
+
+ gimp_vector2_normalize (&result);
+
+ return result;
+}
+/**************************************/
+/* Three dimensional vector functions */
+/**************************************/
+
+/**
+ * gimp_vector3_new:
+ * @x: the X coordinate.
+ * @y: the Y coordinate.
+ * @z: the Z coordinate.
+ *
+ * Creates a #GimpVector3 of coordinate @x, @y and @z.
+ *
+ * Returns: the resulting #GimpVector3.
+ **/
+GimpVector3
+gimp_vector3_new (gdouble x,
+ gdouble y,
+ gdouble z)
+{
+ GimpVector3 vector;
+
+ vector.x = x;
+ vector.y = y;
+ vector.z = z;
+
+ return vector;
+}
+
+/**
+ * gimp_vector3_set:
+ * @vector: a pointer to a #GimpVector3.
+ * @x: the X coordinate.
+ * @y: the Y coordinate.
+ * @z: the Z coordinate.
+ *
+ * Sets the X, Y and Z coordinates of @vector to @x, @y and @z.
+ **/
+void
+gimp_vector3_set (GimpVector3 *vector,
+ gdouble x,
+ gdouble y,
+ gdouble z)
+{
+ vector->x = x;
+ vector->y = y;
+ vector->z = z;
+}
+
+/**
+ * gimp_vector3_length:
+ * @vector: a pointer to a #GimpVector3.
+ *
+ * Computes the length of a 3D vector.
+ *
+ * Returns: the length of @vector (a positive gdouble).
+ **/
+gdouble
+gimp_vector3_length (const GimpVector3 *vector)
+{
+ return (sqrt (vector->x * vector->x +
+ vector->y * vector->y +
+ vector->z * vector->z));
+}
+
+/**
+ * gimp_vector3_length_val:
+ * @vector: a #GimpVector3.
+ *
+ * This function is identical to gimp_vector3_length() but the vector
+ * is passed by value rather than by reference.
+ *
+ * Returns: the length of @vector (a positive gdouble).
+ **/
+gdouble
+gimp_vector3_length_val (GimpVector3 vector)
+{
+ return (sqrt (vector.x * vector.x +
+ vector.y * vector.y +
+ vector.z * vector.z));
+}
+
+/**
+ * gimp_vector3_mul:
+ * @vector: a pointer to a #GimpVector3.
+ * @factor: a scalar.
+ *
+ * Multiplies each component of the @vector by @factor. Note that
+ * this is equivalent to multiplying the vectors length by @factor.
+ **/
+void
+gimp_vector3_mul (GimpVector3 *vector,
+ gdouble factor)
+{
+ vector->x *= factor;
+ vector->y *= factor;
+ vector->z *= factor;
+}
+
+/**
+ * gimp_vector3_mul_val:
+ * @vector: a #GimpVector3.
+ * @factor: a scalar.
+ *
+ * This function is identical to gimp_vector3_mul() but the vector is
+ * passed by value rather than by reference.
+ *
+ * Returns: the resulting #GimpVector3.
+ **/
+GimpVector3
+gimp_vector3_mul_val (GimpVector3 vector,
+ gdouble factor)
+{
+ GimpVector3 result;
+
+ result.x = vector.x * factor;
+ result.y = vector.y * factor;
+ result.z = vector.z * factor;
+
+ return result;
+}
+
+/**
+ * gimp_vector3_normalize:
+ * @vector: a pointer to a #GimpVector3.
+ *
+ * Normalizes the @vector so the length of the @vector is 1.0. The nul
+ * vector will not be changed.
+ **/
+void
+gimp_vector3_normalize (GimpVector3 *vector)
+{
+ gdouble len;
+
+ len = gimp_vector3_length (vector);
+
+ if (len != 0.0)
+ {
+ len = 1.0 / len;
+ vector->x *= len;
+ vector->y *= len;
+ vector->z *= len;
+ }
+ else
+ {
+ *vector = gimp_vector3_zero;
+ }
+}
+
+/**
+ * gimp_vector3_normalize_val:
+ * @vector: a #GimpVector3.
+ *
+ * This function is identical to gimp_vector3_normalize() but the
+ * vector is passed by value rather than by reference.
+ *
+ * Returns: a #GimpVector3 parallel to @vector, pointing in the same
+ * direction but with a length of 1.0.
+ **/
+GimpVector3
+gimp_vector3_normalize_val (GimpVector3 vector)
+{
+ GimpVector3 result;
+ gdouble len;
+
+ len = gimp_vector3_length_val (vector);
+
+ if (len != 0.0)
+ {
+ len = 1.0 / len;
+ result.x = vector.x * len;
+ result.y = vector.y * len;
+ result.z = vector.z * len;
+ return result;
+ }
+ else
+ {
+ return gimp_vector3_zero;
+ }
+}
+
+/**
+ * gimp_vector3_neg:
+ * @vector: a pointer to a #GimpVector3.
+ *
+ * Negates the @vector (i.e. negate all its coordinates).
+ **/
+void
+gimp_vector3_neg (GimpVector3 *vector)
+{
+ vector->x *= -1.0;
+ vector->y *= -1.0;
+ vector->z *= -1.0;
+}
+
+/**
+ * gimp_vector3_neg_val:
+ * @vector: a #GimpVector3.
+ *
+ * This function is identical to gimp_vector3_neg() but the vector
+ * is passed by value rather than by reference.
+ *
+ * Returns: the negated #GimpVector3.
+ **/
+GimpVector3
+gimp_vector3_neg_val (GimpVector3 vector)
+{
+ GimpVector3 result;
+
+ result.x = vector.x * -1.0;
+ result.y = vector.y * -1.0;
+ result.z = vector.z * -1.0;
+
+ return result;
+}
+
+/**
+ * gimp_vector3_add:
+ * @result: destination for the resulting #GimpVector3.
+ * @vector1: a pointer to the first #GimpVector3.
+ * @vector2: a pointer to the second #GimpVector3.
+ *
+ * Computes the sum of two 3D vectors. The resulting #GimpVector3 is
+ * stored in @result.
+ **/
+void
+gimp_vector3_add (GimpVector3 *result,
+ const GimpVector3 *vector1,
+ const GimpVector3 *vector2)
+{
+ result->x = vector1->x + vector2->x;
+ result->y = vector1->y + vector2->y;
+ result->z = vector1->z + vector2->z;
+}
+
+/**
+ * gimp_vector3_add_val:
+ * @vector1: a #GimpVector3.
+ * @vector2: a #GimpVector3.
+ *
+ * This function is identical to gimp_vector3_add() but the vectors
+ * are passed by value rather than by reference.
+ *
+ * Returns: the resulting #GimpVector3.
+ **/
+GimpVector3
+gimp_vector3_add_val (GimpVector3 vector1,
+ GimpVector3 vector2)
+{
+ GimpVector3 result;
+
+ result.x = vector1.x + vector2.x;
+ result.y = vector1.y + vector2.y;
+ result.z = vector1.z + vector2.z;
+
+ return result;
+}
+
+/**
+ * gimp_vector3_sub:
+ * @result: the destination for the resulting #GimpVector3.
+ * @vector1: a pointer to the first #GimpVector3.
+ * @vector2: a pointer to the second #GimpVector3.
+ *
+ * Computes the difference of two 3D vectors (@vector1 minus @vector2).
+ * The resulting #GimpVector3 is stored in @result.
+ **/
+void
+gimp_vector3_sub (GimpVector3 *result,
+ const GimpVector3 *vector1,
+ const GimpVector3 *vector2)
+{
+ result->x = vector1->x - vector2->x;
+ result->y = vector1->y - vector2->y;
+ result->z = vector1->z - vector2->z;
+}
+
+/**
+ * gimp_vector3_sub_val:
+ * @vector1: a #GimpVector3.
+ * @vector2: a #GimpVector3.
+ *
+ * This function is identical to gimp_vector3_sub() but the vectors
+ * are passed by value rather than by reference.
+ *
+ * Returns: the resulting #GimpVector3.
+ **/
+GimpVector3
+gimp_vector3_sub_val (GimpVector3 vector1,
+ GimpVector3 vector2)
+{
+ GimpVector3 result;
+
+ result.x = vector1.x - vector2.x;
+ result.y = vector1.y - vector2.y;
+ result.z = vector1.z - vector2.z;
+
+ return result;
+}
+
+/**
+ * gimp_vector3_inner_product:
+ * @vector1: a pointer to the first #GimpVector3.
+ * @vector2: a pointer to the second #GimpVector3.
+ *
+ * Computes the inner (dot) product of two 3D vectors. This product
+ * is zero if and only if the two vectors are orthogonal.
+ *
+ * Returns: The inner product.
+ **/
+gdouble
+gimp_vector3_inner_product (const GimpVector3 *vector1,
+ const GimpVector3 *vector2)
+{
+ return (vector1->x * vector2->x +
+ vector1->y * vector2->y +
+ vector1->z * vector2->z);
+}
+
+/**
+ * gimp_vector3_inner_product_val:
+ * @vector1: the first #GimpVector3.
+ * @vector2: the second #GimpVector3.
+ *
+ * This function is identical to gimp_vector3_inner_product() but the
+ * vectors are passed by value rather than by reference.
+ *
+ * Returns: The inner product.
+ **/
+gdouble
+gimp_vector3_inner_product_val (GimpVector3 vector1,
+ GimpVector3 vector2)
+{
+ return (vector1.x * vector2.x +
+ vector1.y * vector2.y +
+ vector1.z * vector2.z);
+}
+
+/**
+ * gimp_vector3_cross_product:
+ * @vector1: a pointer to the first #GimpVector3.
+ * @vector2: a pointer to the second #GimpVector3.
+ *
+ * Compute the cross product of two vectors. The result is a
+ * #GimpVector3 which is orthogonal to both @vector1 and @vector2. If
+ * @vector1 and @vector2 and parallel, the result will be the nul
+ * vector.
+ *
+ * This function can be used to compute the normal of the plane
+ * defined by @vector1 and @vector2.
+ *
+ * Returns: The cross product.
+ **/
+GimpVector3
+gimp_vector3_cross_product (const GimpVector3 *vector1,
+ const GimpVector3 *vector2)
+{
+ GimpVector3 normal;
+
+ normal.x = vector1->y * vector2->z - vector1->z * vector2->y;
+ normal.y = vector1->z * vector2->x - vector1->x * vector2->z;
+ normal.z = vector1->x * vector2->y - vector1->y * vector2->x;
+
+ return normal;
+}
+
+/**
+ * gimp_vector3_cross_product_val:
+ * @vector1: the first #GimpVector3.
+ * @vector2: the second #GimpVector3.
+ *
+ * This function is identical to gimp_vector3_cross_product() but the
+ * vectors are passed by value rather than by reference.
+ *
+ * Returns: The cross product.
+ **/
+GimpVector3
+gimp_vector3_cross_product_val (GimpVector3 vector1,
+ GimpVector3 vector2)
+{
+ GimpVector3 normal;
+
+ normal.x = vector1.y * vector2.z - vector1.z * vector2.y;
+ normal.y = vector1.z * vector2.x - vector1.x * vector2.z;
+ normal.z = vector1.x * vector2.y - vector1.y * vector2.x;
+
+ return normal;
+}
+
+/**
+ * gimp_vector3_rotate:
+ * @vector: a pointer to a #GimpVector3.
+ * @alpha: the angle (in radian) of rotation around the Z axis.
+ * @beta: the angle (in radian) of rotation around the Y axis.
+ * @gamma: the angle (in radian) of rotation around the X axis.
+ *
+ * Rotates the @vector around the three axis (Z, Y, and X) by @alpha,
+ * @beta and @gamma, respectively.
+ *
+ * Note that the order of the rotation is very important. If you
+ * expect a vector to be rotated around X, and then around Y, you will
+ * have to call this function twice. Also, it is often wise to call
+ * this function with only one of @alpha, @beta and @gamma non-zero.
+ **/
+void
+gimp_vector3_rotate (GimpVector3 *vector,
+ gdouble alpha,
+ gdouble beta,
+ gdouble gamma)
+{
+ GimpVector3 s, t;
+
+ /* First we rotate it around the Z axis (XY plane).. */
+ /* ================================================= */
+
+ s.x = cos (alpha) * vector->x + sin (alpha) * vector->y;
+ s.y = cos (alpha) * vector->y - sin (alpha) * vector->x;
+
+ /* ..then around the Y axis (XZ plane).. */
+ /* ===================================== */
+
+ t = s;
+
+ vector->x = cos (beta) *t.x + sin (beta) * vector->z;
+ s.z = cos (beta) *vector->z - sin (beta) * t.x;
+
+ /* ..and at last around the X axis (YZ plane) */
+ /* ========================================== */
+
+ vector->y = cos (gamma) * t.y + sin (gamma) * s.z;
+ vector->z = cos (gamma) * s.z - sin (gamma) * t.y;
+}
+
+/**
+ * gimp_vector3_rotate_val:
+ * @vector: a #GimpVector3.
+ * @alpha: the angle (in radian) of rotation around the Z axis.
+ * @beta: the angle (in radian) of rotation around the Y axis.
+ * @gamma: the angle (in radian) of rotation around the X axis.
+ *
+ * This function is identical to gimp_vector3_rotate() but the vectors
+ * are passed by value rather than by reference.
+ *
+ * Returns: the rotated vector.
+ **/
+GimpVector3
+gimp_vector3_rotate_val (GimpVector3 vector,
+ gdouble alpha,
+ gdouble beta,
+ gdouble gamma)
+{
+ GimpVector3 s, t, result;
+
+ /* First we rotate it around the Z axis (XY plane).. */
+ /* ================================================= */
+
+ s.x = cos (alpha) * vector.x + sin (alpha) * vector.y;
+ s.y = cos (alpha) * vector.y - sin (alpha) * vector.x;
+
+ /* ..then around the Y axis (XZ plane).. */
+ /* ===================================== */
+
+ t = s;
+
+ result.x = cos (beta) *t.x + sin (beta) * vector.z;
+ s.z = cos (beta) *vector.z - sin (beta) * t.x;
+
+ /* ..and at last around the X axis (YZ plane) */
+ /* ========================================== */
+
+ result.y = cos (gamma) * t.y + sin (gamma) * s.z;
+ result.z = cos (gamma) * s.z - sin (gamma) * t.y;
+
+ return result;
+}
+
+/**
+ * gimp_vector_2d_to_3d:
+ * @sx: the abscissa of the upper-left screen rectangle.
+ * @sy: the ordinate of the upper-left screen rectangle.
+ * @w: the width of the screen rectangle.
+ * @h: the height of the screen rectangle.
+ * @x: the abscissa of the point in the screen rectangle to map.
+ * @y: the ordinate of the point in the screen rectangle to map.
+ * @vp: the position of the observer.
+ * @p: the resulting point.
+ *
+ * \"Compute screen (sx, sy) - (sx + w, sy + h) to 3D unit square
+ * mapping. The plane to map to is given in the z field of p. The
+ * observer is located at position vp (vp->z != 0.0).\"
+ *
+ * In other words, this computes the projection of the point (@x, @y)
+ * to the plane z = @p->z (parallel to XY), from the @vp point of view
+ * through the screen (@sx, @sy)->(@sx + @w, @sy + @h)
+ **/
+
+void
+gimp_vector_2d_to_3d (gint sx,
+ gint sy,
+ gint w,
+ gint h,
+ gint x,
+ gint y,
+ const GimpVector3 *vp,
+ GimpVector3 *p)
+{
+ gdouble t = 0.0;
+
+ if (vp->x != 0.0)
+ t = (p->z - vp->z) / vp->z;
+
+ if (t != 0.0)
+ {
+ p->x = vp->x + t * (vp->x - ((gdouble) (x - sx) / (gdouble) w));
+ p->y = vp->y + t * (vp->y - ((gdouble) (y - sy) / (gdouble) h));
+ }
+ else
+ {
+ p->x = (gdouble) (x - sx) / (gdouble) w;
+ p->y = (gdouble) (y - sy) / (gdouble) h;
+ }
+}
+
+/**
+ * gimp_vector_2d_to_3d_val:
+ * @sx: the abscissa of the upper-left screen rectangle.
+ * @sy: the ordinate of the upper-left screen rectangle.
+ * @w: the width of the screen rectangle.
+ * @h: the height of the screen rectangle.
+ * @x: the abscissa of the point in the screen rectangle to map.
+ * @y: the ordinate of the point in the screen rectangle to map.
+ * @vp: position of the observer.
+ * @p: the resulting point.
+ *
+ * This function is identical to gimp_vector_2d_to_3d() but the
+ * position of the @observer and the resulting point @p are passed by
+ * value rather than by reference.
+ *
+ * Returns: the computed #GimpVector3 point.
+ **/
+GimpVector3
+gimp_vector_2d_to_3d_val (gint sx,
+ gint sy,
+ gint w,
+ gint h,
+ gint x,
+ gint y,
+ GimpVector3 vp,
+ GimpVector3 p)
+{
+ GimpVector3 result;
+ gdouble t = 0.0;
+
+ if (vp.x != 0.0)
+ t = (p.z - vp.z) / vp.z;
+
+ if (t != 0.0)
+ {
+ result.x = vp.x + t * (vp.x - ((gdouble) (x - sx) / (gdouble) w));
+ result.y = vp.y + t * (vp.y - ((gdouble) (y - sy) / (gdouble) h));
+ }
+ else
+ {
+ result.x = (gdouble) (x - sx) / (gdouble) w;
+ result.y = (gdouble) (y - sy) / (gdouble) h;
+ }
+
+ result.z = 0;
+ return result;
+}
+
+/**
+ * gimp_vector_3d_to_2d:
+ * @sx: the abscissa of the upper-left screen rectangle.
+ * @sy: the ordinate of the upper-left screen rectangle.
+ * @w: the width of the screen rectangle.
+ * @h: the height of the screen rectangle.
+ * @x: the abscissa of the point in the screen rectangle to map (return value).
+ * @y: the ordinate of the point in the screen rectangle to map (return value).
+ * @vp: position of the observer.
+ * @p: the 3D point to project to the plane.
+ *
+ * Convert the given 3D point to 2D (project it onto the viewing
+ * plane, (sx, sy, 0) - (sx + w, sy + h, 0). The input is assumed to
+ * be in the unit square (0, 0, z) - (1, 1, z). The viewpoint of the
+ * observer is passed in vp.
+ *
+ * This is basically the opposite of gimp_vector_2d_to_3d().
+ **/
+void
+gimp_vector_3d_to_2d (gint sx,
+ gint sy,
+ gint w,
+ gint h,
+ gdouble *x,
+ gdouble *y,
+ const GimpVector3 *vp,
+ const GimpVector3 *p)
+{
+ gdouble t;
+ GimpVector3 dir;
+
+ gimp_vector3_sub (&dir, p, vp);
+ gimp_vector3_normalize (&dir);
+
+ if (dir.z != 0.0)
+ {
+ t = (-1.0 * vp->z) / dir.z;
+ *x = (gdouble) sx + ((vp->x + t * dir.x) * (gdouble) w);
+ *y = (gdouble) sy + ((vp->y + t * dir.y) * (gdouble) h);
+ }
+ else
+ {
+ *x = (gdouble) sx + (p->x * (gdouble) w);
+ *y = (gdouble) sy + (p->y * (gdouble) h);
+ }
+}