gimpvector.c 26.8 KB
Newer Older
1 2 3
/* LIBGIMP - The GIMP Library
 * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
 *
4 5
 * gimpvector.c
 *
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
 * 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 2 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, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

/**********************************************/
/* A little collection of useful vector stuff */
/**********************************************/

Sven Neumann's avatar
Sven Neumann committed
30 31
#include "config.h"

32
#include <glib-object.h>
33

34 35
#include "gimpmath.h"

36

37 38 39 40
/*************************/
/* Some useful constants */
/*************************/

41 42 43
static const GimpVector2 gimp_vector2_zero =   { 0.0, 0.0 };
static const GimpVector2 gimp_vector2_unit_x = { 1.0, 0.0 };
static const GimpVector2 gimp_vector2_unit_y = { 0.0, 1.0 };
44

45 46 47 48
static const GimpVector3 gimp_vector3_zero =   { 0.0, 0.0, 0.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 };
49 50

/**************************************/
51
/* Two   dimensional vector functions */
52 53
/**************************************/

54
/**
55 56 57
 * gimp_vector2_new:
 * @x: the X coordinate.
 * @y: the Y coordinate.
58
 *
59
 * Creates a #GimpVector2 of coordinates @x and @y.
60
 *
61
 * Returns: the resulting #GimpVector2.
62
 **/
63 64 65
GimpVector2
gimp_vector2_new (gdouble x,
                  gdouble y)
66
{
67 68 69 70 71 72
  GimpVector2 vector;

  vector.x = x;
  vector.y = y;

  return vector;
73 74
}

75
/**
76 77 78 79
 * gimp_vector2_set:
 * @vector: a pointer to a #GimpVector2.
 * @x: the X coordinate.
 * @y: the Y coordinate.
80
 *
81
 * Sets the X and Y coordinates of @vector to @x and @y.
82
 **/
83 84 85 86
void
gimp_vector2_set (GimpVector2 *vector,
                  gdouble      x,
                  gdouble      y)
87
{
88 89
  vector->x = x;
  vector->y = y;
90 91
}

92
/**
93 94
 * gimp_vector2_length:
 * @vector: a pointer to a #GimpVector2.
95
 *
96
 * Computes the length of a 2D vector.
97
 *
98
 * Returns: the length of @vector (a positive gdouble).
99
 **/
100 101
gdouble
gimp_vector2_length (const GimpVector2 *vector)
102
{
103
  return (sqrt (vector->x * vector->x + vector->y * vector->y));
104 105
}

106
/**
107 108
 * gimp_vector2_length_val:
 * @vector: a #GimpVector2.
109
 *
110 111
 * This function is identical to gimp_vector2_length() but the
 * vector is passed by value rather than by reference.
112
 *
113
 * Returns: the length of @vector (a positive gdouble).
114
 **/
115 116
gdouble
gimp_vector2_length_val (GimpVector2 vector)
117
{
118
  return (sqrt (vector.x * vector.x + vector.y * vector.y));
119 120
}

121
/**
122 123 124
 * gimp_vector2_mul:
 * @vector: a pointer to a #GimpVector2.
 * @factor: a scalar.
125
 *
126 127
 * Multiplies each component of the @vector by @factor. Note that this
 * is equivalent to multiplying the vectors length by @factor.
128
 **/
129 130 131
void
gimp_vector2_mul (GimpVector2 *vector,
                  gdouble      factor)
132
{
133 134
  vector->x *= factor;
  vector->y *= factor;
135 136
}

137
/**
138 139 140
 * gimp_vector2_mul_val:
 * @vector: a #GimpVector2.
 * @factor: a scalar.
141
 *
142 143
 * This function is identical to gimp_vector2_mul() but the vector is
 * passed by value rather than by reference.
144
 *
145
 * Returns: the resulting #GimpVector2.
146
 **/
147 148 149
GimpVector2
gimp_vector2_mul_val (GimpVector2 vector,
                      gdouble     factor)
150
{
151 152 153 154 155 156
  GimpVector2 result;

  result.x = vector.x * factor;
  result.y = vector.y * factor;

  return result;
157 158
}

159

160 161
/**
 * gimp_vector2_normalize:
162
 * @vector: a pointer to a #GimpVector2.
163
 *
164 165
 * Normalizes the @vector so the length of the @vector is 1.0. The nul
 * vector will not be changed.
166
 **/
167
void
168
gimp_vector2_normalize (GimpVector2 *vector)
169 170 171
{
  gdouble len;

172
  len = gimp_vector2_length (vector);
Sven Neumann's avatar
Sven Neumann committed
173

174
  if (len != 0.0)
175 176
    {
      len = 1.0 / len;
177 178
      vector->x *= len;
      vector->y *= len;
179 180 181
    }
  else
    {
182
      *vector = gimp_vector2_zero;
183 184 185
    }
}

186 187
/**
 * gimp_vector2_normalize_val:
188
 * @vector: a #GimpVector2.
189
 *
190 191
 * This function is identical to gimp_vector2_normalize() but the
 * vector is passed by value rather than by reference.
192 193
 *
 * Returns: a #GimpVector2 parallel to @vector, pointing in the same
194
 * direction but with a length of 1.0.
195
 **/
196 197 198 199
GimpVector2
gimp_vector2_normalize_val (GimpVector2 vector)
{
  GimpVector2 normalized;
Sven Neumann's avatar
Sven Neumann committed
200
  gdouble     len;
201 202

  len = gimp_vector2_length_val (vector);
Sven Neumann's avatar
Sven Neumann committed
203

204
  if (len != 0.0)
205 206 207 208 209 210 211 212 213 214 215 216
    {
      len = 1.0 / len;
      normalized.x = vector.x * len;
      normalized.y = vector.y * len;
      return normalized;
    }
  else
    {
      return gimp_vector2_zero;
    }
}

217
/**
218 219
 * gimp_vector2_neg:
 * @vector: a pointer to a #GimpVector2.
220
 *
221
 * Negates the @vector (i.e. negate all its coordinates).
222
 **/
223
void
224
gimp_vector2_neg (GimpVector2 *vector)
225
{
226 227
  vector->x *= -1.0;
  vector->y *= -1.0;
228 229
}

230
/**
231 232
 * gimp_vector2_neg_val:
 * @vector: a #GimpVector2.
233
 *
234 235
 * This function is identical to gimp_vector2_neg() but the vector
 * is passed by value rather than by reference.
236
 *
237
 * Returns: the negated #GimpVector2.
238
 **/
239
GimpVector2
240
gimp_vector2_neg_val (GimpVector2 vector)
241 242
{
  GimpVector2 result;
243

244 245
  result.x = vector.x * -1.0;
  result.y = vector.y * -1.0;
Sven Neumann's avatar
Sven Neumann committed
246

247 248 249
  return result;
}

250 251
/**
 * gimp_vector2_add:
252 253 254
 * @result: destination for the resulting #GimpVector2.
 * @vector1: a pointer to the first #GimpVector2.
 * @vector2: a pointer to the second #GimpVector2.
255
 *
256 257
 * Computes the sum of two 2D vectors. The resulting #GimpVector2 is
 * stored in @result.
258 259 260
 **/
void
gimp_vector2_add (GimpVector2       *result,
261 262
                  const GimpVector2 *vector1,
                  const GimpVector2 *vector2)
263 264 265 266 267 268 269
{
  result->x = vector1->x + vector2->x;
  result->y = vector1->y + vector2->y;
}

/**
 * gimp_vector2_add_val:
270 271
 * @vector1: the first #GimpVector2.
 * @vector2: the second #GimpVector2.
272
 *
273 274
 * This function is identical to gimp_vector2_add() but the vectors
 * are passed by value rather than by reference.
275 276 277 278 279
 *
 * Returns: the resulting #GimpVector2.
 **/
GimpVector2
gimp_vector2_add_val (GimpVector2 vector1,
280
                      GimpVector2 vector2)
281 282 283 284 285
{
  GimpVector2 result;

  result.x = vector1.x + vector2.x;
  result.y = vector1.y + vector2.y;
286

287 288 289 290 291
  return result;
}

/**
 * gimp_vector2_sub:
292 293 294
 * @result: the destination for the resulting #GimpVector2.
 * @vector1: a pointer to the first #GimpVector2.
 * @vector2: a pointer to the second #GimpVector2.
295 296
 *
 * Computes the difference of two 2D vectors (@vector1 minus @vector2).
297
 * The resulting #GimpVector2 is stored in @result.
298
 **/
299
void
Sven Neumann's avatar
Sven Neumann committed
300
gimp_vector2_sub (GimpVector2       *result,
301 302
                  const GimpVector2 *vector1,
                  const GimpVector2 *vector2)
303
{
304 305
  result->x = vector1->x - vector2->x;
  result->y = vector1->y - vector2->y;
306 307
}

308 309
/**
 * gimp_vector2_sub_val:
310 311
 * @vector1: the first #GimpVector2.
 * @vector2: the second #GimpVector2.
312
 *
313 314
 * This function is identical to gimp_vector2_sub() but the vectors
 * are passed by value rather than by reference.
315 316 317
 *
 * Returns: the resulting #GimpVector2.
 **/
318 319
GimpVector2
gimp_vector2_sub_val (GimpVector2 vector1,
320
                      GimpVector2 vector2)
321 322
{
  GimpVector2 result;
323

324 325
  result.x = vector1.x - vector2.x;
  result.y = vector1.y - vector2.y;
326

327 328 329
  return result;
}

330
/**
331 332 333
 * gimp_vector2_inner_product:
 * @vector1: a pointer to the first #GimpVector2.
 * @vector2: a pointer to the second #GimpVector2.
334
 *
335 336 337 338
 * Computes the inner (dot) product of two 2D vectors.
 * This product is zero if and only if the two vectors are orthognal.
 *
 * Returns: The inner product.
339
 **/
340 341 342
gdouble
gimp_vector2_inner_product (const GimpVector2 *vector1,
                            const GimpVector2 *vector2)
343
{
344
  return (vector1->x * vector2->x + vector1->y * vector2->y);
345 346
}

347
/**
348 349 350
 * gimp_vector2_inner_product_val:
 * @vector1: the first #GimpVector2.
 * @vector2: the second #GimpVector2.
351
 *
352 353
 * This function is identical to gimp_vector2_inner_product() but the
 * vectors are passed by value rather than by reference.
354
 *
355
 * Returns: The inner product.
356
 **/
357 358 359
gdouble
gimp_vector2_inner_product_val (GimpVector2 vector1,
                                GimpVector2 vector2)
360
{
361
  return (vector1.x * vector2.x + vector1.y * vector2.y);
362 363
}

364
/**
365 366 367
 * gimp_vector2_cross_product:
 * @vector1: a pointer to the first #GimpVector2.
 * @vector2: a pointer to the second #GimpVector2.
368
 *
369 370 371 372 373 374 375 376 377
 * Compute the cross product of two vectors. The result is a
 * #GimpVector2 which is orthognal 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.
378
 **/
379 380 381
GimpVector2
gimp_vector2_cross_product (const GimpVector2 *vector1,
                            const GimpVector2 *vector2)
382
{
383 384 385 386 387 388
  GimpVector2 normal;

  normal.x = vector1->x * vector2->y - vector1->y * vector2->x;
  normal.y = vector1->y * vector2->x - vector1->x * vector2->y;

  return normal;
389 390
}

391
/**
392 393 394
 * gimp_vector2_cross_product_val:
 * @vector1: the first #GimpVector2.
 * @vector2: the second #GimpVector2.
395
 *
396 397
 * This function is identical to gimp_vector2_cross_product() but the
 * vectors are passed by value rather than by reference.
398
 *
399
 * Returns: The cross product.
400
 **/
401
GimpVector2
402 403
gimp_vector2_cross_product_val (GimpVector2 vector1,
                                GimpVector2 vector2)
404
{
405
  GimpVector2 normal;
406

407 408
  normal.x = vector1.x * vector2.y - vector1.y * vector2.x;
  normal.y = vector1.y * vector2.x - vector1.x * vector2.y;
409

410
  return normal;
411 412
}

413 414
/**
 * gimp_vector2_rotate:
415 416
 * @vector: a pointer to a #GimpVector2.
 * @alpha: an angle (in radians).
417
 *
418
 * Rotates the @vector counterclockwise by @alpha radians.
419
 **/
420
void
421
gimp_vector2_rotate (GimpVector2 *vector,
422
                     gdouble      alpha)
423
{
424
  GimpVector2 result;
425

426 427
  result.x = cos (alpha) * vector->x + sin (alpha) * vector->y;
  result.y = cos (alpha) * vector->y - sin (alpha) * vector->x;
428

429
  *vector = result;
430 431
}

432 433
/**
 * gimp_vector2_rotate_val:
434 435
 * @vector: a #GimpVector2.
 * @alpha: an angle (in radians).
436
 *
437 438
 * This function is identical to gimp_vector2_rotate() but the vector
 * is passed by value rather than by reference.
439
 *
440 441
 * Returns: a #GimpVector2 representing @vector rotated by @alpha
 * radians.
442
 **/
443 444
GimpVector2
gimp_vector2_rotate_val (GimpVector2 vector,
445
                         gdouble     alpha)
446 447 448 449 450 451 452 453 454
{
  GimpVector2 result;

  result.x = cos (alpha) * vector.x + sin (alpha) * vector.y;
  result.y = cos (alpha) * vector.y - sin (alpha) * vector.x;

  return result;
}

455 456 457 458
/**************************************/
/* Three dimensional vector functions */
/**************************************/

459
/**
460 461 462 463
 * gimp_vector3_new:
 * @x: the X coordinate.
 * @y: the Y coordinate.
 * @z: the Z coordinate.
464
 *
465
 * Creates a #GimpVector3 of coordinate @x, @y and @z.
466
 *
467
 * Returns: the resulting #GimpVector3.
468
 **/
469
GimpVector3
470 471 472
gimp_vector3_new (gdouble  x,
                  gdouble  y,
                  gdouble  z)
473
{
474
  GimpVector3 vector;
475

476 477 478
  vector.x = x;
  vector.y = y;
  vector.z = z;
479

480
  return vector;
481 482
}

483
/**
484 485 486 487 488
 * gimp_vector3_set:
 * @vector: a pointer to a #GimpVector3.
 * @x: the X coordinate.
 * @y: the Y coordinate.
 * @z: the Z coordinate.
489
 *
490
 * Sets the X, Y and Z coordinates of @vector to @x, @y and @z.
491
 **/
492 493 494 495 496
void
gimp_vector3_set (GimpVector3 *vector,
                  gdouble      x,
                  gdouble      y,
                  gdouble      z)
497
{
498 499 500
  vector->x = x;
  vector->y = y;
  vector->z = z;
501 502
}

503 504
/**
 * gimp_vector3_length:
505
 * @vector: a pointer to a #GimpVector3.
506
 *
507
 * Computes the length of a 3D vector.
508
 *
509
 * Returns: the length of @vector (a positive gdouble).
510
 **/
511
gdouble
Sven Neumann's avatar
Sven Neumann committed
512
gimp_vector3_length (const GimpVector3 *vector)
513
{
514
  return (sqrt (vector->x * vector->x +
515 516
                vector->y * vector->y +
                vector->z * vector->z));
517 518
}

519 520
/**
 * gimp_vector3_length_val:
521
 * @vector: a #GimpVector3.
522
 *
523 524
 * This function is identical to gimp_vector3_length() but the vector
 * is passed by value rather than by reference.
525
 *
526
 * Returns: the length of @vector (a positive gdouble).
527
 **/
528 529 530 531
gdouble
gimp_vector3_length_val (GimpVector3 vector)
{
  return (sqrt (vector.x * vector.x +
532 533
                vector.y * vector.y +
                vector.z * vector.z));
534 535
}

536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575
/**
 * 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;
}

576 577
/**
 * gimp_vector3_normalize:
578
 * @vector: a pointer to a #GimpVector3.
579
 *
580 581
 * Normalizes the @vector so the length of the @vector is 1.0. The nul
 * vector will not be changed.
582
 **/
583
void
584
gimp_vector3_normalize (GimpVector3 *vector)
585 586 587
{
  gdouble len;

588
  len = gimp_vector3_length (vector);
Sven Neumann's avatar
Sven Neumann committed
589

590 591 592
  if (len != 0.0)
    {
      len = 1.0 / len;
593 594 595
      vector->x *= len;
      vector->y *= len;
      vector->z *= len;
596 597 598
    }
  else
    {
599
      *vector = gimp_vector3_zero;
600 601 602
    }
}

603 604
/**
 * gimp_vector3_normalize_val:
605
 * @vector: a #GimpVector3.
606
 *
607 608
 * This function is identical to gimp_vector3_normalize() but the
 * vector is passed by value rather than by reference.
609
 *
610 611
 * Returns: a #GimpVector3 parallel to @vector, pointing in the same
 * direction but with a length of 1.0.
612
 **/
613 614 615 616
GimpVector3
gimp_vector3_normalize_val (GimpVector3 vector)
{
  GimpVector3 result;
Sven Neumann's avatar
Sven Neumann committed
617
  gdouble     len;
618 619

  len = gimp_vector3_length_val (vector);
Sven Neumann's avatar
Sven Neumann committed
620

621 622 623 624 625 626 627 628 629 630 631 632 633 634
  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;
    }
}

635
/**
636 637
 * gimp_vector3_neg:
 * @vector: a pointer to a #GimpVector3.
638
 *
639
 * Negates the @vector (i.e. negate all its coordinates).
640
 **/
641
void
642
gimp_vector3_neg (GimpVector3 *vector)
643
{
644 645 646
  vector->x *= -1.0;
  vector->y *= -1.0;
  vector->z *= -1.0;
647 648
}

649
/**
650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692
 * 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.
693
 *
694 695
 * This function is identical to gimp_vector3_add() but the vectors
 * are passed by value rather than by reference.
696 697 698
 *
 * Returns: the resulting #GimpVector3.
 **/
699
GimpVector3
700 701
gimp_vector3_add_val (GimpVector3 vector1,
                      GimpVector3 vector2)
702 703
{
  GimpVector3 result;
704

705 706 707
  result.x = vector1.x + vector2.x;
  result.y = vector1.y + vector2.y;
  result.z = vector1.z + vector2.z;
708 709 710 711

  return result;
}

712 713
/**
 * gimp_vector3_sub:
714 715 716
 * @result: the destination for the resulting #GimpVector3.
 * @vector1: a pointer to the first #GimpVector3.
 * @vector2: a pointer to the second #GimpVector3.
717 718
 *
 * Computes the difference of two 3D vectors (@vector1 minus @vector2).
719
 * The resulting #GimpVector3 is stored in @result.
720
 **/
721
void
Sven Neumann's avatar
Sven Neumann committed
722
gimp_vector3_sub (GimpVector3       *result,
723 724
                  const GimpVector3 *vector1,
                  const GimpVector3 *vector2)
725
{
726 727 728
  result->x = vector1->x - vector2->x;
  result->y = vector1->y - vector2->y;
  result->z = vector1->z - vector2->z;
729 730
}

731 732
/**
 * gimp_vector3_sub_val:
733 734
 * @vector1: a #GimpVector3.
 * @vector2: a #GimpVector3.
735
 *
736 737
 * This function is identical to gimp_vector3_sub() but the vectors
 * are passed by value rather than by reference.
738 739 740
 *
 * Returns: the resulting #GimpVector3.
 **/
741
GimpVector3
742
gimp_vector3_sub_val (GimpVector3 vector1,
743
                     GimpVector3 vector2)
744 745 746 747 748 749 750 751 752 753
{
  GimpVector3 result;

  result.x = vector1.x - vector2.x;
  result.y = vector1.y - vector2.y;
  result.z = vector1.z - vector2.z;

  return result;
}

754
/**
755 756 757 758 759 760
 * 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 orthognal.
761
 *
762
 * Returns: The inner product.
763
 **/
764 765 766
gdouble
gimp_vector3_inner_product (const GimpVector3 *vector1,
                            const GimpVector3 *vector2)
767
{
768 769 770
  return (vector1->x * vector2->x +
          vector1->y * vector2->y +
          vector1->z * vector2->z);
771 772
}

773
/**
774 775 776
 * gimp_vector3_inner_product_val:
 * @vector1: the first #GimpVector3.
 * @vector2: the second #GimpVector3.
777
 *
778 779
 * This function is identical to gimp_vector3_inner_product() but the
 * vectors are passed by value rather than by reference.
780
 *
781
 * Returns: The inner product.
782
 **/
783 784 785
gdouble
gimp_vector3_inner_product_val (GimpVector3 vector1,
                                GimpVector3 vector2)
786
{
787 788 789
  return (vector1.x * vector2.x +
          vector1.y * vector2.y +
          vector1.z * vector2.z);
790 791
}

792
/**
793 794 795
 * gimp_vector3_cross_product:
 * @vector1: a pointer to the first #GimpVector3.
 * @vector2: a pointer to the second #GimpVector3.
796
 *
797 798 799 800
 * Compute the cross product of two vectors. The result is a
 * #GimpVector3 which is orthognal to both @vector1 and @vector2. If
 * @vector1 and @vector2 and parallel, the result will be the nul
 * vector.
801
 *
802 803
 * This function can be used to compute the normal of the plane
 * defined by @vector1 and @vector2.
804
 *
805
 * Returns: The cross product.
806
 **/
807
GimpVector3
808 809
gimp_vector3_cross_product (const GimpVector3 *vector1,
                            const GimpVector3 *vector2)
810
{
811
  GimpVector3 normal;
812

813 814 815
  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;
816

817
  return normal;
818 819
}

820
/**
821 822 823
 * gimp_vector3_cross_product_val:
 * @vector1: the first #GimpVector3.
 * @vector2: the second #GimpVector3.
824
 *
825 826
 * This function is identical to gimp_vector3_cross_product() but the
 * vectors are passed by value rather than by reference.
827
 *
828
 * Returns: The cross product.
829
 **/
830
GimpVector3
831 832
gimp_vector3_cross_product_val (GimpVector3 vector1,
                                GimpVector3 vector2)
833
{
834
  GimpVector3 normal;
835

836 837 838
  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;
839

840
  return normal;
841 842
}

843 844
/**
 * gimp_vector3_rotate:
845
 * @vector: a pointer to a #GimpVector3.
846 847 848 849
 * @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.
 *
850 851
 * Rotates the @vector around the three axis (Z, Y, and X) by @alpha,
 * @beta and @gamma, respectively.
852
 *
853 854 855 856
 * 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.
857
 **/
858
void
859
gimp_vector3_rotate (GimpVector3 *vector,
860 861 862
                     gdouble      alpha,
                     gdouble      beta,
                     gdouble      gamma)
863 864 865 866 867 868
{
  GimpVector3 s, t;

  /* First we rotate it around the Z axis (XY plane).. */
  /* ================================================= */

869 870
  s.x = cos (alpha) * vector->x + sin (alpha) * vector->y;
  s.y = cos (alpha) * vector->y - sin (alpha) * vector->x;
871 872 873 874 875 876

  /* ..then around the Y axis (XZ plane).. */
  /* ===================================== */

  t = s;

877 878
  vector->x = cos (beta) *t.x       + sin (beta) * vector->z;
  s.z       = cos (beta) *vector->z - sin (beta) * t.x;
879 880 881 882

  /* ..and at last around the X axis (YZ plane) */
  /* ========================================== */

883 884
  vector->y = cos (gamma) * t.y + sin (gamma) * s.z;
  vector->z = cos (gamma) * s.z - sin (gamma) * t.y;
885 886
}

887 888
/**
 * gimp_vector3_rotate_val:
889
 * @vector: a #GimpVector3.
890 891 892 893
 * @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.
 *
894 895
 * This function is identical to gimp_vector3_rotate() but the vectors
 * are passed by value rather than by reference.
896 897 898
 *
 * Returns: the rotated vector.
 **/
899
GimpVector3
900
gimp_vector3_rotate_val (GimpVector3 vector,
901 902 903
                         gdouble     alpha,
                         gdouble     beta,
                         gdouble     gamma)
904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929
{
  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;
}

930 931 932 933 934 935 936 937
/**
 * gimp_vector_2d_to_3d:
 * @sx: the abscisse 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 abscisse of the point in the screen rectangle to map.
 * @y: the ordinate of the point in the screen rectangle to map.
938 939
 * @vp: the position of the observer.
 * @p: the resulting point.
940
 *
941 942 943
 * \"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).\"
944
 *
945 946 947
 * 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)
948
 **/
949 950

void
Sven Neumann's avatar
Sven Neumann committed
951
gimp_vector_2d_to_3d (gint               sx,
952 953 954 955 956 957 958
                      gint               sy,
                      gint               w,
                      gint               h,
                      gint               x,
                      gint               y,
                      const GimpVector3 *vp,
                      GimpVector3       *p)
959 960 961 962 963 964 965 966 967 968 969 970 971 972
{
  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;
973
      p->y = (gdouble) (y - sy) / (gdouble) h;
974 975 976
    }
}

977 978 979 980 981 982 983 984
/**
 * gimp_vector_2d_to_3d_val:
 * @sx: the abscisse 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 abscisse of the point in the screen rectangle to map.
 * @y: the ordinate of the point in the screen rectangle to map.
985 986
 * @vp: position of the observer.
 * @p: the resulting point.
987
 *
988 989 990
 * 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.
991 992 993
 *
 * Returns: the computed #GimpVector3 point.
 **/
994
GimpVector3
995
gimp_vector_2d_to_3d_val (gint        sx,
996 997 998 999 1000 1001 1002
                          gint        sy,
                          gint        w,
                          gint        h,
                          gint        x,
                          gint        y,
                          GimpVector3 vp,
                          GimpVector3 p)
1003
{
1004
  GimpVector3 result;
Sven Neumann's avatar
Sven Neumann committed
1005
  gdouble     t = 0.0;
1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017

  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;
1018
      result.y = (gdouble) (y - sy) / (gdouble) h;
1019
    }
1020

1021
  result.z = 0;
1022 1023 1024
  return result;
}

1025 1026 1027 1028 1029 1030 1031 1032
/**
 * gimp_vector_3d_to_2d:
 * @sx: the abscisse 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 abscisse 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).
1033 1034
 * @vp: position of the observer.
 * @p: the 3D point to project to the plane.
1035
 *
1036 1037 1038 1039
 * 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.
1040
 *
1041
 * This is basically the opposite of gimp_vector_2d_to_3d().
1042
 **/
1043
void
Sven Neumann's avatar
Sven Neumann committed
1044
gimp_vector_3d_to_2d (gint               sx,
1045 1046 1047 1048 1049 1050 1051
                      gint               sy,
                      gint               w,
                      gint               h,
                      gdouble           *x,
                      gdouble           *y,
                      const GimpVector3 *vp,
                      const GimpVector3 *p)
Sven Neumann's avatar
Sven Neumann committed
1052 1053
{
  gdouble     t;
1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070
  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);
    }
}