gimpvector.c 27.9 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
 * The gimp_vector* functions were taken from:
 * GCK - The General Convenience Kit
 * Copyright (C) 1996 Tom Bech
 *
10
 * This library is free software: you can redistribute it and/or
11 12
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
13
 * version 3 of the License, or (at your option) any later version.
14 15 16 17 18 19 20
 *
 * 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
21
 * License along with this library.  If not, see
22
 * <https://www.gnu.org/licenses/>.
23 24 25 26 27 28
 */

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

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

31
#include <glib-object.h>
32

33 34
#include "gimpmath.h"

35

36 37 38 39 40 41 42 43 44 45
/**
 * 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.
 **/


46 47 48 49
/*************************/
/* Some useful constants */
/*************************/

50
static const GimpVector2 gimp_vector2_zero =   { 0.0, 0.0 };
51
#if 0
52 53
static const GimpVector2 gimp_vector2_unit_x = { 1.0, 0.0 };
static const GimpVector2 gimp_vector2_unit_y = { 0.0, 1.0 };
54
#endif
55

56
static const GimpVector3 gimp_vector3_zero =   { 0.0, 0.0, 0.0 };
57
#if 0
58 59 60
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 };
61
#endif
62 63

/**************************************/
64
/* Two   dimensional vector functions */
65 66
/**************************************/

67
/**
68 69 70
 * gimp_vector2_new:
 * @x: the X coordinate.
 * @y: the Y coordinate.
71
 *
72
 * Creates a #GimpVector2 of coordinates @x and @y.
73
 *
74
 * Returns: the resulting #GimpVector2.
75
 **/
76 77 78
GimpVector2
gimp_vector2_new (gdouble x,
                  gdouble y)
79
{
80 81 82 83 84 85
  GimpVector2 vector;

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

  return vector;
86 87
}

88
/**
89 90 91 92
 * gimp_vector2_set:
 * @vector: a pointer to a #GimpVector2.
 * @x: the X coordinate.
 * @y: the Y coordinate.
93
 *
94
 * Sets the X and Y coordinates of @vector to @x and @y.
95
 **/
96 97 98 99
void
gimp_vector2_set (GimpVector2 *vector,
                  gdouble      x,
                  gdouble      y)
100
{
101 102
  vector->x = x;
  vector->y = y;
103 104
}

105
/**
106 107
 * gimp_vector2_length:
 * @vector: a pointer to a #GimpVector2.
108
 *
109
 * Computes the length of a 2D vector.
110
 *
111
 * Returns: the length of @vector (a positive gdouble).
112
 **/
113 114
gdouble
gimp_vector2_length (const GimpVector2 *vector)
115
{
116
  return (sqrt (vector->x * vector->x + vector->y * vector->y));
117 118
}

119
/**
120 121
 * gimp_vector2_length_val:
 * @vector: a #GimpVector2.
122
 *
123 124
 * This function is identical to gimp_vector2_length() but the
 * vector is passed by value rather than by reference.
125
 *
126
 * Returns: the length of @vector (a positive gdouble).
127
 **/
128 129
gdouble
gimp_vector2_length_val (GimpVector2 vector)
130
{
131
  return (sqrt (vector.x * vector.x + vector.y * vector.y));
132 133
}

134
/**
135 136 137
 * gimp_vector2_mul:
 * @vector: a pointer to a #GimpVector2.
 * @factor: a scalar.
138
 *
139 140
 * Multiplies each component of the @vector by @factor. Note that this
 * is equivalent to multiplying the vectors length by @factor.
141
 **/
142 143 144
void
gimp_vector2_mul (GimpVector2 *vector,
                  gdouble      factor)
145
{
146 147
  vector->x *= factor;
  vector->y *= factor;
148 149
}

150
/**
151 152 153
 * gimp_vector2_mul_val:
 * @vector: a #GimpVector2.
 * @factor: a scalar.
154
 *
155 156
 * This function is identical to gimp_vector2_mul() but the vector is
 * passed by value rather than by reference.
157
 *
158
 * Returns: the resulting #GimpVector2.
159
 **/
160 161 162
GimpVector2
gimp_vector2_mul_val (GimpVector2 vector,
                      gdouble     factor)
163
{
164 165 166 167 168 169
  GimpVector2 result;

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

  return result;
170 171
}

172

173 174
/**
 * gimp_vector2_normalize:
175
 * @vector: a pointer to a #GimpVector2.
176
 *
177 178
 * Normalizes the @vector so the length of the @vector is 1.0. The nul
 * vector will not be changed.
179
 **/
180
void
181
gimp_vector2_normalize (GimpVector2 *vector)
182 183 184
{
  gdouble len;

185
  len = gimp_vector2_length (vector);
Sven Neumann's avatar
Sven Neumann committed
186

187
  if (len != 0.0)
188 189
    {
      len = 1.0 / len;
190 191
      vector->x *= len;
      vector->y *= len;
192 193 194
    }
  else
    {
195
      *vector = gimp_vector2_zero;
196 197 198
    }
}

199 200
/**
 * gimp_vector2_normalize_val:
201
 * @vector: a #GimpVector2.
202
 *
203 204
 * This function is identical to gimp_vector2_normalize() but the
 * vector is passed by value rather than by reference.
205 206
 *
 * Returns: a #GimpVector2 parallel to @vector, pointing in the same
207
 * direction but with a length of 1.0.
208
 **/
209 210 211 212
GimpVector2
gimp_vector2_normalize_val (GimpVector2 vector)
{
  GimpVector2 normalized;
Sven Neumann's avatar
Sven Neumann committed
213
  gdouble     len;
214 215

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

217
  if (len != 0.0)
218 219 220 221 222 223 224 225 226 227 228 229
    {
      len = 1.0 / len;
      normalized.x = vector.x * len;
      normalized.y = vector.y * len;
      return normalized;
    }
  else
    {
      return gimp_vector2_zero;
    }
}

230
/**
231 232
 * gimp_vector2_neg:
 * @vector: a pointer to a #GimpVector2.
233
 *
234
 * Negates the @vector (i.e. negate all its coordinates).
235
 **/
236
void
237
gimp_vector2_neg (GimpVector2 *vector)
238
{
239 240
  vector->x *= -1.0;
  vector->y *= -1.0;
241 242
}

243
/**
244 245
 * gimp_vector2_neg_val:
 * @vector: a #GimpVector2.
246
 *
247 248
 * This function is identical to gimp_vector2_neg() but the vector
 * is passed by value rather than by reference.
249
 *
250
 * Returns: the negated #GimpVector2.
251
 **/
252
GimpVector2
253
gimp_vector2_neg_val (GimpVector2 vector)
254 255
{
  GimpVector2 result;
256

257 258
  result.x = vector.x * -1.0;
  result.y = vector.y * -1.0;
Sven Neumann's avatar
Sven Neumann committed
259

260 261 262
  return result;
}

263 264
/**
 * gimp_vector2_add:
265 266 267
 * @result: destination for the resulting #GimpVector2.
 * @vector1: a pointer to the first #GimpVector2.
 * @vector2: a pointer to the second #GimpVector2.
268
 *
269 270
 * Computes the sum of two 2D vectors. The resulting #GimpVector2 is
 * stored in @result.
271 272 273
 **/
void
gimp_vector2_add (GimpVector2       *result,
274 275
                  const GimpVector2 *vector1,
                  const GimpVector2 *vector2)
276 277 278 279 280 281 282
{
  result->x = vector1->x + vector2->x;
  result->y = vector1->y + vector2->y;
}

/**
 * gimp_vector2_add_val:
283 284
 * @vector1: the first #GimpVector2.
 * @vector2: the second #GimpVector2.
285
 *
286 287
 * This function is identical to gimp_vector2_add() but the vectors
 * are passed by value rather than by reference.
288 289 290 291 292
 *
 * Returns: the resulting #GimpVector2.
 **/
GimpVector2
gimp_vector2_add_val (GimpVector2 vector1,
293
                      GimpVector2 vector2)
294 295 296 297 298
{
  GimpVector2 result;

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

300 301 302 303 304
  return result;
}

/**
 * gimp_vector2_sub:
305 306 307
 * @result: the destination for the resulting #GimpVector2.
 * @vector1: a pointer to the first #GimpVector2.
 * @vector2: a pointer to the second #GimpVector2.
308 309
 *
 * Computes the difference of two 2D vectors (@vector1 minus @vector2).
310
 * The resulting #GimpVector2 is stored in @result.
311
 **/
312
void
Sven Neumann's avatar
Sven Neumann committed
313
gimp_vector2_sub (GimpVector2       *result,
314 315
                  const GimpVector2 *vector1,
                  const GimpVector2 *vector2)
316
{
317 318
  result->x = vector1->x - vector2->x;
  result->y = vector1->y - vector2->y;
319 320
}

321 322
/**
 * gimp_vector2_sub_val:
323 324
 * @vector1: the first #GimpVector2.
 * @vector2: the second #GimpVector2.
325
 *
326 327
 * This function is identical to gimp_vector2_sub() but the vectors
 * are passed by value rather than by reference.
328 329 330
 *
 * Returns: the resulting #GimpVector2.
 **/
331 332
GimpVector2
gimp_vector2_sub_val (GimpVector2 vector1,
333
                      GimpVector2 vector2)
334 335
{
  GimpVector2 result;
336

337 338
  result.x = vector1.x - vector2.x;
  result.y = vector1.y - vector2.y;
339

340 341 342
  return result;
}

343
/**
344 345 346
 * gimp_vector2_inner_product:
 * @vector1: a pointer to the first #GimpVector2.
 * @vector2: a pointer to the second #GimpVector2.
347
 *
348
 * Computes the inner (dot) product of two 2D vectors.
349
 * This product is zero if and only if the two vectors are orthogonal.
350 351
 *
 * Returns: The inner product.
352
 **/
353 354 355
gdouble
gimp_vector2_inner_product (const GimpVector2 *vector1,
                            const GimpVector2 *vector2)
356
{
357
  return (vector1->x * vector2->x + vector1->y * vector2->y);
358 359
}

360
/**
361 362 363
 * gimp_vector2_inner_product_val:
 * @vector1: the first #GimpVector2.
 * @vector2: the second #GimpVector2.
364
 *
365 366
 * This function is identical to gimp_vector2_inner_product() but the
 * vectors are passed by value rather than by reference.
367
 *
368
 * Returns: The inner product.
369
 **/
370 371 372
gdouble
gimp_vector2_inner_product_val (GimpVector2 vector1,
                                GimpVector2 vector2)
373
{
374
  return (vector1.x * vector2.x + vector1.y * vector2.y);
375 376
}

377
/**
378 379 380
 * gimp_vector2_cross_product:
 * @vector1: a pointer to the first #GimpVector2.
 * @vector2: a pointer to the second #GimpVector2.
381
 *
382
 * Compute the cross product of two vectors. The result is a
383
 * #GimpVector2 which is orthogonal to both @vector1 and @vector2. If
384 385 386 387 388 389 390
 * @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.
391
 **/
392 393 394
GimpVector2
gimp_vector2_cross_product (const GimpVector2 *vector1,
                            const GimpVector2 *vector2)
395
{
396 397 398 399 400 401
  GimpVector2 normal;

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

  return normal;
402 403
}

404
/**
405 406 407
 * gimp_vector2_cross_product_val:
 * @vector1: the first #GimpVector2.
 * @vector2: the second #GimpVector2.
408
 *
409 410
 * This function is identical to gimp_vector2_cross_product() but the
 * vectors are passed by value rather than by reference.
411
 *
412
 * Returns: The cross product.
413
 **/
414
GimpVector2
415 416
gimp_vector2_cross_product_val (GimpVector2 vector1,
                                GimpVector2 vector2)
417
{
418
  GimpVector2 normal;
419

420 421
  normal.x = vector1.x * vector2.y - vector1.y * vector2.x;
  normal.y = vector1.y * vector2.x - vector1.x * vector2.y;
422

423
  return normal;
424 425
}

426 427
/**
 * gimp_vector2_rotate:
428 429
 * @vector: a pointer to a #GimpVector2.
 * @alpha: an angle (in radians).
430
 *
431
 * Rotates the @vector counterclockwise by @alpha radians.
432
 **/
433
void
434
gimp_vector2_rotate (GimpVector2 *vector,
435
                     gdouble      alpha)
436
{
437
  GimpVector2 result;
438

439 440
  result.x = cos (alpha) * vector->x + sin (alpha) * vector->y;
  result.y = cos (alpha) * vector->y - sin (alpha) * vector->x;
441

442
  *vector = result;
443 444
}

445 446
/**
 * gimp_vector2_rotate_val:
447 448
 * @vector: a #GimpVector2.
 * @alpha: an angle (in radians).
449
 *
450 451
 * This function is identical to gimp_vector2_rotate() but the vector
 * is passed by value rather than by reference.
452
 *
453 454
 * Returns: a #GimpVector2 representing @vector rotated by @alpha
 * radians.
455
 **/
456 457
GimpVector2
gimp_vector2_rotate_val (GimpVector2 vector,
458
                         gdouble     alpha)
459 460 461 462 463 464 465 466 467
{
  GimpVector2 result;

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

  return result;
}

468 469 470 471 472 473 474
/**
 * 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.
475
 *
476
 * Since: 2.8
477 478
 **/
GimpVector2
479
gimp_vector2_normal (GimpVector2 *vector)
480 481
{
  GimpVector2 result;
482 483 484 485 486 487

  result.x = - vector->y;
  result.y = vector->x;

  gimp_vector2_normalize (&result);

488 489 490 491 492 493 494 495 496 497 498
  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.
499
 *
500
 * Since: 2.8
501 502
 **/
GimpVector2
503
gimp_vector2_normal_val (GimpVector2 vector)
504 505
{
  GimpVector2 result;
506 507 508 509

  result.x = - vector.y;
  result.y = vector.x;

510
  gimp_vector2_normalize (&result);
511

512 513
  return result;
}
514 515 516 517
/**************************************/
/* Three dimensional vector functions */
/**************************************/

518
/**
519 520 521 522
 * gimp_vector3_new:
 * @x: the X coordinate.
 * @y: the Y coordinate.
 * @z: the Z coordinate.
523
 *
524
 * Creates a #GimpVector3 of coordinate @x, @y and @z.
525
 *
526
 * Returns: the resulting #GimpVector3.
527
 **/
528
GimpVector3
529 530 531
gimp_vector3_new (gdouble  x,
                  gdouble  y,
                  gdouble  z)
532
{
533
  GimpVector3 vector;
534

535 536 537
  vector.x = x;
  vector.y = y;
  vector.z = z;
538

539
  return vector;
540 541
}

542
/**
543 544 545 546 547
 * gimp_vector3_set:
 * @vector: a pointer to a #GimpVector3.
 * @x: the X coordinate.
 * @y: the Y coordinate.
 * @z: the Z coordinate.
548
 *
549
 * Sets the X, Y and Z coordinates of @vector to @x, @y and @z.
550
 **/
551 552 553 554 555
void
gimp_vector3_set (GimpVector3 *vector,
                  gdouble      x,
                  gdouble      y,
                  gdouble      z)
556
{
557 558 559
  vector->x = x;
  vector->y = y;
  vector->z = z;
560 561
}

562 563
/**
 * gimp_vector3_length:
564
 * @vector: a pointer to a #GimpVector3.
565
 *
566
 * Computes the length of a 3D vector.
567
 *
568
 * Returns: the length of @vector (a positive gdouble).
569
 **/
570
gdouble
Sven Neumann's avatar
Sven Neumann committed
571
gimp_vector3_length (const GimpVector3 *vector)
572
{
573
  return (sqrt (vector->x * vector->x +
574 575
                vector->y * vector->y +
                vector->z * vector->z));
576 577
}

578 579
/**
 * gimp_vector3_length_val:
580
 * @vector: a #GimpVector3.
581
 *
582 583
 * This function is identical to gimp_vector3_length() but the vector
 * is passed by value rather than by reference.
584
 *
585
 * Returns: the length of @vector (a positive gdouble).
586
 **/
587 588 589 590
gdouble
gimp_vector3_length_val (GimpVector3 vector)
{
  return (sqrt (vector.x * vector.x +
591 592
                vector.y * vector.y +
                vector.z * vector.z));
593 594
}

595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634
/**
 * 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;
}

635 636
/**
 * gimp_vector3_normalize:
637
 * @vector: a pointer to a #GimpVector3.
638
 *
639 640
 * Normalizes the @vector so the length of the @vector is 1.0. The nul
 * vector will not be changed.
641
 **/
642
void
643
gimp_vector3_normalize (GimpVector3 *vector)
644 645 646
{
  gdouble len;

647
  len = gimp_vector3_length (vector);
Sven Neumann's avatar
Sven Neumann committed
648

649 650 651
  if (len != 0.0)
    {
      len = 1.0 / len;
652 653 654
      vector->x *= len;
      vector->y *= len;
      vector->z *= len;
655 656 657
    }
  else
    {
658
      *vector = gimp_vector3_zero;
659 660 661
    }
}

662 663
/**
 * gimp_vector3_normalize_val:
664
 * @vector: a #GimpVector3.
665
 *
666 667
 * This function is identical to gimp_vector3_normalize() but the
 * vector is passed by value rather than by reference.
668
 *
669 670
 * Returns: a #GimpVector3 parallel to @vector, pointing in the same
 * direction but with a length of 1.0.
671
 **/
672 673 674 675
GimpVector3
gimp_vector3_normalize_val (GimpVector3 vector)
{
  GimpVector3 result;
Sven Neumann's avatar
Sven Neumann committed
676
  gdouble     len;
677 678

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

680 681 682 683 684 685 686 687 688 689 690 691 692 693
  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;
    }
}

694
/**
695 696
 * gimp_vector3_neg:
 * @vector: a pointer to a #GimpVector3.
697
 *
698
 * Negates the @vector (i.e. negate all its coordinates).
699
 **/
700
void
701
gimp_vector3_neg (GimpVector3 *vector)
702
{
703 704 705
  vector->x *= -1.0;
  vector->y *= -1.0;
  vector->z *= -1.0;
706 707
}

708
/**
709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751
 * 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.
752
 *
753 754
 * This function is identical to gimp_vector3_add() but the vectors
 * are passed by value rather than by reference.
755 756 757
 *
 * Returns: the resulting #GimpVector3.
 **/
758
GimpVector3
759 760
gimp_vector3_add_val (GimpVector3 vector1,
                      GimpVector3 vector2)
761 762
{
  GimpVector3 result;
763

764 765 766
  result.x = vector1.x + vector2.x;
  result.y = vector1.y + vector2.y;
  result.z = vector1.z + vector2.z;
767 768 769 770

  return result;
}

771 772
/**
 * gimp_vector3_sub:
773 774 775
 * @result: the destination for the resulting #GimpVector3.
 * @vector1: a pointer to the first #GimpVector3.
 * @vector2: a pointer to the second #GimpVector3.
776 777
 *
 * Computes the difference of two 3D vectors (@vector1 minus @vector2).
778
 * The resulting #GimpVector3 is stored in @result.
779
 **/
780
void
Sven Neumann's avatar
Sven Neumann committed
781
gimp_vector3_sub (GimpVector3       *result,
782 783
                  const GimpVector3 *vector1,
                  const GimpVector3 *vector2)
784
{
785 786 787
  result->x = vector1->x - vector2->x;
  result->y = vector1->y - vector2->y;
  result->z = vector1->z - vector2->z;
788 789
}

790 791
/**
 * gimp_vector3_sub_val:
792 793
 * @vector1: a #GimpVector3.
 * @vector2: a #GimpVector3.
794
 *
795 796
 * This function is identical to gimp_vector3_sub() but the vectors
 * are passed by value rather than by reference.
797 798 799
 *
 * Returns: the resulting #GimpVector3.
 **/
800
GimpVector3
801
gimp_vector3_sub_val (GimpVector3 vector1,
802
                     GimpVector3 vector2)
803 804 805 806 807 808 809 810 811 812
{
  GimpVector3 result;

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

  return result;
}

813
/**
814 815 816 817 818
 * 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
819
 * is zero if and only if the two vectors are orthogonal.
820
 *
821
 * Returns: The inner product.
822
 **/
823 824 825
gdouble
gimp_vector3_inner_product (const GimpVector3 *vector1,
                            const GimpVector3 *vector2)
826
{
827 828 829
  return (vector1->x * vector2->x +
          vector1->y * vector2->y +
          vector1->z * vector2->z);
830 831
}

832
/**
833 834 835
 * gimp_vector3_inner_product_val:
 * @vector1: the first #GimpVector3.
 * @vector2: the second #GimpVector3.
836
 *
837 838
 * This function is identical to gimp_vector3_inner_product() but the
 * vectors are passed by value rather than by reference.
839
 *
840
 * Returns: The inner product.
841
 **/
842 843 844
gdouble
gimp_vector3_inner_product_val (GimpVector3 vector1,
                                GimpVector3 vector2)
845
{
846 847 848
  return (vector1.x * vector2.x +
          vector1.y * vector2.y +
          vector1.z * vector2.z);
849 850
}

851
/**
852 853 854
 * gimp_vector3_cross_product:
 * @vector1: a pointer to the first #GimpVector3.
 * @vector2: a pointer to the second #GimpVector3.
855
 *
856
 * Compute the cross product of two vectors. The result is a
857
 * #GimpVector3 which is orthogonal to both @vector1 and @vector2. If
858 859
 * @vector1 and @vector2 and parallel, the result will be the nul
 * vector.
860
 *
861 862
 * This function can be used to compute the normal of the plane
 * defined by @vector1 and @vector2.
863
 *
864
 * Returns: The cross product.
865
 **/
866
GimpVector3
867 868
gimp_vector3_cross_product (const GimpVector3 *vector1,
                            const GimpVector3 *vector2)
869
{
870
  GimpVector3 normal;
871

872 873 874
  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;
875

876
  return normal;
877 878
}

879
/**
880 881 882
 * gimp_vector3_cross_product_val:
 * @vector1: the first #GimpVector3.
 * @vector2: the second #GimpVector3.
883
 *
884 885
 * This function is identical to gimp_vector3_cross_product() but the
 * vectors are passed by value rather than by reference.
886
 *
887
 * Returns: The cross product.
888
 **/
889
GimpVector3
890 891
gimp_vector3_cross_product_val (GimpVector3 vector1,
                                GimpVector3 vector2)
892
{
893
  GimpVector3 normal;
894

895 896 897
  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;
898

899
  return normal;
900 901
}

902 903
/**
 * gimp_vector3_rotate:
904
 * @vector: a pointer to a #GimpVector3.
905 906 907 908
 * @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.
 *
909 910
 * Rotates the @vector around the three axis (Z, Y, and X) by @alpha,
 * @beta and @gamma, respectively.
911
 *
912 913 914 915
 * 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.
916
 **/
917
void
918
gimp_vector3_rotate (GimpVector3 *vector,
919 920 921
                     gdouble      alpha,
                     gdouble      beta,
                     gdouble      gamma)
922 923 924 925 926 927
{
  GimpVector3 s, t;

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

928 929
  s.x = cos (alpha) * vector->x + sin (alpha) * vector->y;
  s.y = cos (alpha) * vector->y - sin (alpha) * vector->x;
930 931 932 933 934 935

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

  t = s;

936 937
  vector->x = cos (beta) *t.x       + sin (beta) * vector->z;
  s.z       = cos (beta) *vector->z - sin (beta) * t.x;
938 939 940 941

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

942 943
  vector->y = cos (gamma) * t.y + sin (gamma) * s.z;
  vector->z = cos (gamma) * s.z - sin (gamma) * t.y;
944 945
}

946 947
/**
 * gimp_vector3_rotate_val:
948
 * @vector: a #GimpVector3.
949 950 951 952
 * @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.
 *
953 954
 * This function is identical to gimp_vector3_rotate() but the vectors
 * are passed by value rather than by reference.
955 956 957
 *
 * Returns: the rotated vector.
 **/
958
GimpVector3
959
gimp_vector3_rotate_val (GimpVector3 vector,
960 961 962
                         gdouble     alpha,
                         gdouble     beta,
                         gdouble     gamma)
963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988
{
  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;
}

989 990
/**
 * gimp_vector_2d_to_3d:
991
 * @sx: the abscissa of the upper-left screen rectangle.
992 993 994
 * @sy: the ordinate of the upper-left screen rectangle.
 * @w: the width of the screen rectangle.
 * @h: the height of the screen rectangle.
995
 * @x: the abscissa of the point in the screen rectangle to map.
996
 * @y: the ordinate of the point in the screen rectangle to map.
997 998
 * @vp: the position of the observer.
 * @p: the resulting point.
999
 *
1000 1001 1002
 * \"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).\"
1003
 *
1004 1005 1006
 * 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)
1007
 **/
1008 1009

void
Sven Neumann's avatar
Sven Neumann committed
1010
gimp_vector_2d_to_3d (gint               sx,
1011 1012 1013 1014 1015 1016 1017
                      gint               sy,
                      gint               w,
                      gint               h,
                      gint               x,
                      gint               y,
                      const GimpVector3 *vp,
                      GimpVector3       *p)
1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031
{
  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;
1032
      p->y = (gdouble) (y - sy) / (gdouble) h;
1033 1034 1035
    }
}

1036 1037
/**
 * gimp_vector_2d_to_3d_val:
1038
 * @sx: the abscissa of the upper-left screen rectangle.
1039 1040 1041
 * @sy: the ordinate of the upper-left screen rectangle.
 * @w: the width of the screen rectangle.
 * @h: the height of the screen rectangle.
1042
 * @x: the abscissa of the point in the screen rectangle to map.
1043
 * @y: the ordinate of the point in the screen rectangle to map.
1044 1045
 * @vp: position of the observer.
 * @p: the resulting point.
1046
 *
1047 1048 1049
 * 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.
1050 1051 1052
 *
 * Returns: the computed #GimpVector3 point.
 **/
1053
GimpVector3
1054
gimp_vector_2d_to_3d_val (gint        sx,
1055 1056 1057 1058 1059 1060 1061
                          gint        sy,
                          gint        w,
                          gint        h,
                          gint        x,
                          gint        y,
                          GimpVector3 vp,
                          GimpVector3 p)
1062
{
1063
  GimpVector3 result;
Sven Neumann's avatar
Sven Neumann committed
1064
  gdouble     t = 0.0;
1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076

  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;
1077
      result.y = (gdouble) (y - sy) / (gdouble) h;
1078
    }
1079

1080
  result.z = 0;
1081 1082 1083
  return result;
}

1084 1085
/**
 * gimp_vector_3d_to_2d:
1086
 * @sx: the abscissa of the upper-left screen rectangle.
1087 1088 1089
 * @sy: the ordinate of the upper-left screen rectangle.
 * @w: the width of the screen rectangle.
 * @h: the height of the screen rectangle.
1090
 * @x: the abscissa of the point in the screen rectangle to map (return value).
1091
 * @y: the ordinate of the point in the screen rectangle to map (return value).
1092 1093
 * @vp: position of the observer.
 * @p: the 3D point to project to the plane.
1094
 *
1095 1096 1097 1098
 * 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.
1099
 *
1100
 * This is basically the opposite of gimp_vector_2d_to_3d().
1101
 **/
1102
void
Sven Neumann's avatar
Sven Neumann committed
1103
gimp_vector_3d_to_2d (gint               sx,
1104 1105 1106 1107 1108 1109 1110
                      gint               sy,
                      gint               w,
                      gint               h,
                      gdouble           *x,
                      gdouble           *y,
                      const GimpVector3 *vp,
                      const GimpVector3 *p)
Sven Neumann's avatar
Sven Neumann committed
1111 1112
{
  gdouble     t;
1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129
  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);
    }
}