POLYGON.C 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059
  1. /****************************************************************************
  2. * polygon.c
  3. *
  4. * This module implements functions that manipulate polygons.
  5. *
  6. * This module was written by Dieter Bayer [DB].
  7. *
  8. * from Persistence of Vision(tm) Ray Tracer
  9. * Copyright 1996,1999 Persistence of Vision Team
  10. *---------------------------------------------------------------------------
  11. * NOTICE: This source code file is provided so that users may experiment
  12. * with enhancements to POV-Ray and to port the software to platforms other
  13. * than those supported by the POV-Ray Team. There are strict rules under
  14. * which you are permitted to use this file. The rules are in the file
  15. * named POVLEGAL.DOC which should be distributed with this file.
  16. * If POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  17. * Team Coordinator by email to team-coord@povray.org or visit us on the web at
  18. * http://www.povray.org. The latest version of POV-Ray may be found at this site.
  19. *
  20. * This program is based on the popular DKB raytracer version 2.12.
  21. * DKBTrace was originally written by David K. Buck.
  22. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  23. *
  24. *****************************************************************************/
  25. /****************************************************************************
  26. *
  27. * Explanation:
  28. *
  29. * Syntax:
  30. *
  31. * ---
  32. *
  33. * The "inside polygon"-test was taken from:
  34. *
  35. * E. Haines, "An Introduction to Ray-Tracing", ..., pp. 53-59
  36. *
  37. * ---
  38. *
  39. * May 1994 : Creation. [DB]
  40. *
  41. * Oct 1994 : Changed polygon structure. Polygon points are now stored
  42. * in a seperate structure. This - together with the use of
  43. * a transformation - allows to keep just one point definition
  44. * for multiple copies of one polygon. [DB]
  45. *
  46. *****************************************************************************/
  47. #include "frame.h"
  48. #include "vector.h"
  49. #include "povproto.h"
  50. #include "matrices.h"
  51. #include "objects.h"
  52. #include "polygon.h"
  53. #include "povray.h"
  54. /*****************************************************************************
  55. * Local preprocessor defines
  56. ******************************************************************************/
  57. /* Minimal intersection depth for a valid intersection. */
  58. #define DEPTH_TOLERANCE 1.0e-8
  59. /* If |x| < ZERO_TOLERANCE x is assumed to be 0. */
  60. #define ZERO_TOLERANCE 1.0e-10
  61. /*****************************************************************************
  62. * Static functions
  63. ******************************************************************************/
  64. static int intersect_poylgon (RAY *Ray, POLYGON *Polyg, DBL *Depth);
  65. static int in_polygon (int Number, UV_VECT *Points, DBL u, DBL v);
  66. static int All_Polygon_Intersections (OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack);
  67. static int Inside_Polygon (VECTOR point, OBJECT *Object);
  68. static void Polygon_Normal (VECTOR Result, OBJECT *Object, INTERSECTION *Inter);
  69. static POLYGON *Copy_Polygon (OBJECT *Object);
  70. static void Translate_Polygon (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
  71. static void Rotate_Polygon (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
  72. static void Scale_Polygon (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
  73. static void Transform_Polygon (OBJECT *Object, TRANSFORM *Trans);
  74. static void Invert_Polygon (OBJECT *Object);
  75. static void Destroy_Polygon (OBJECT *Object);
  76. static void Compute_Polygon_BBox (POLYGON *Polyg);
  77. /*****************************************************************************
  78. * Local variables
  79. ******************************************************************************/
  80. static METHODS Polygon_Methods =
  81. {
  82. All_Polygon_Intersections,
  83. Inside_Polygon, Polygon_Normal,
  84. (COPY_METHOD)Copy_Polygon,
  85. Translate_Polygon, Rotate_Polygon,
  86. Scale_Polygon, Transform_Polygon, Invert_Polygon, Destroy_Polygon
  87. };
  88. /*****************************************************************************
  89. *
  90. * FUNCTION
  91. *
  92. * All_Polygon_Intersections
  93. *
  94. * INPUT
  95. *
  96. * Object - Object
  97. * Ray - Ray
  98. * Depth_Stack - Intersection stack
  99. *
  100. * OUTPUT
  101. *
  102. * Depth_Stack
  103. *
  104. * RETURNS
  105. *
  106. * int - TRUE, if a intersection was found
  107. *
  108. * AUTHOR
  109. *
  110. * Dieter Bayer
  111. *
  112. * DESCRIPTION
  113. *
  114. * Determine ray/polygon intersection and clip intersection found.
  115. *
  116. * CHANGES
  117. *
  118. * May 1994 : Creation.
  119. *
  120. ******************************************************************************/
  121. static int All_Polygon_Intersections(OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack)
  122. {
  123. DBL Depth;
  124. VECTOR IPoint;
  125. if (intersect_poylgon(Ray, (POLYGON *)Object, &Depth))
  126. {
  127. VEvaluateRay(IPoint, Ray->Initial, Depth, Ray->Direction);
  128. if (Point_In_Clip(IPoint, Object->Clip))
  129. {
  130. push_entry(Depth, IPoint, Object, Depth_Stack);
  131. return(TRUE);
  132. }
  133. }
  134. return(FALSE);
  135. }
  136. /*****************************************************************************
  137. *
  138. * FUNCTION
  139. *
  140. * intersect_poylgon
  141. *
  142. * INPUT
  143. *
  144. * Ray - Ray
  145. * Polyg - Polygon
  146. * Depth - Depth of intersection found
  147. *
  148. * OUTPUT
  149. *
  150. * Depth
  151. *
  152. * RETURNS
  153. *
  154. * int - TRUE if intersection found
  155. *
  156. * AUTHOR
  157. *
  158. * Dieter Bayer
  159. *
  160. * DESCRIPTION
  161. *
  162. * Determine ray/polygon intersection.
  163. *
  164. * CHANGES
  165. *
  166. * May 1994 : Creation.
  167. *
  168. ******************************************************************************/
  169. static int intersect_poylgon(RAY *Ray, POLYGON *Polyg, DBL *Depth)
  170. {
  171. DBL x, y, len;
  172. VECTOR p, d;
  173. /* Don't test degenerate polygons. */
  174. if (Test_Flag(Polyg, DEGENERATE_FLAG))
  175. {
  176. return(FALSE);
  177. }
  178. Increase_Counter(stats[Ray_Polygon_Tests]);
  179. /* Transform the ray into the polygon space. */
  180. MInvTransPoint(p, Ray->Initial, Polyg->Trans);
  181. MInvTransDirection(d, Ray->Direction, Polyg->Trans);
  182. VLength(len, d);
  183. VInverseScaleEq(d, len);
  184. /* Intersect ray with the plane in which the polygon lies. */
  185. if (fabs(d[Z]) < ZERO_TOLERANCE)
  186. {
  187. return(FALSE);
  188. }
  189. *Depth = -p[Z] / d[Z];
  190. if ((*Depth < DEPTH_TOLERANCE) || (*Depth > Max_Distance))
  191. {
  192. return(FALSE);
  193. }
  194. /* Does the intersection point lie inside the polygon? */
  195. x = p[X] + *Depth * d[X];
  196. y = p[Y] + *Depth * d[Y];
  197. if (in_polygon(Polyg->Data->Number, Polyg->Data->Points, x, y))
  198. {
  199. Increase_Counter(stats[Ray_Polygon_Tests_Succeeded]);
  200. *Depth /= len;
  201. return (TRUE);
  202. }
  203. else
  204. {
  205. return (FALSE);
  206. }
  207. }
  208. /*****************************************************************************
  209. *
  210. * FUNCTION
  211. *
  212. * Inside_Polygon
  213. *
  214. * INPUT
  215. *
  216. * IPoint - Intersection point
  217. * Object - Object
  218. *
  219. * OUTPUT
  220. *
  221. * RETURNS
  222. *
  223. * int - always FALSE
  224. *
  225. * AUTHOR
  226. *
  227. * Dieter Bayer
  228. *
  229. * DESCRIPTION
  230. *
  231. * Polygons can't be used in CSG.
  232. *
  233. * CHANGES
  234. *
  235. * May 1994 : Creation.
  236. *
  237. ******************************************************************************/
  238. static int Inside_Polygon(VECTOR IPoint, OBJECT *Object)
  239. {
  240. return(FALSE);
  241. }
  242. /*****************************************************************************
  243. *
  244. * FUNCTION
  245. *
  246. * Polygon_Normal
  247. *
  248. * INPUT
  249. *
  250. * Result - Normal vector
  251. * Object - Object
  252. * Inter - Intersection found
  253. *
  254. * OUTPUT
  255. *
  256. * Result
  257. *
  258. * RETURNS
  259. *
  260. * AUTHOR
  261. *
  262. * Dieter Bayer
  263. *
  264. * DESCRIPTION
  265. *
  266. * Calculate the normal of the polygon in a given point.
  267. *
  268. * CHANGES
  269. *
  270. * May 1994 : Creation.
  271. *
  272. ******************************************************************************/
  273. static void Polygon_Normal(VECTOR Result, OBJECT *Object, INTERSECTION *Inter)
  274. {
  275. Assign_Vector(Result, ((POLYGON *)Object)->S_Normal);
  276. }
  277. /*****************************************************************************
  278. *
  279. * FUNCTION
  280. *
  281. * Translate_Polygon
  282. *
  283. * INPUT
  284. *
  285. * Object - Object
  286. * Vector - Translation vector
  287. *
  288. * OUTPUT
  289. *
  290. * Object
  291. *
  292. * RETURNS
  293. *
  294. * AUTHOR
  295. *
  296. * Dieter Bayer
  297. *
  298. * DESCRIPTION
  299. *
  300. * Translate a polygon.
  301. *
  302. * CHANGES
  303. *
  304. * May 1994 : Creation.
  305. *
  306. ******************************************************************************/
  307. static void Translate_Polygon(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  308. {
  309. Transform_Polygon(Object, Trans);
  310. }
  311. /*****************************************************************************
  312. *
  313. * FUNCTION
  314. *
  315. * Rotate_Polygon
  316. *
  317. * INPUT
  318. *
  319. * Object - Object
  320. * Vector - Rotation vector
  321. *
  322. * OUTPUT
  323. *
  324. * Object
  325. *
  326. * RETURNS
  327. *
  328. * AUTHOR
  329. *
  330. * Dieter Bayer
  331. *
  332. * DESCRIPTION
  333. *
  334. * Rotate a polygon.
  335. *
  336. * CHANGES
  337. *
  338. * May 1994 : Creation.
  339. *
  340. ******************************************************************************/
  341. static void Rotate_Polygon(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  342. {
  343. Transform_Polygon(Object, Trans);
  344. }
  345. /*****************************************************************************
  346. *
  347. * FUNCTION
  348. *
  349. * Scale_Polygon
  350. *
  351. * INPUT
  352. *
  353. * Object - Object
  354. * Vector - Scaling vector
  355. *
  356. * OUTPUT
  357. *
  358. * Object
  359. *
  360. * RETURNS
  361. *
  362. * AUTHOR
  363. *
  364. * Dieter Bayer
  365. *
  366. * DESCRIPTION
  367. *
  368. * Scale a polygon.
  369. *
  370. * CHANGES
  371. *
  372. * May 1994 : Creation.
  373. *
  374. ******************************************************************************/
  375. static void Scale_Polygon(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  376. {
  377. Transform_Polygon(Object, Trans);
  378. }
  379. /*****************************************************************************
  380. *
  381. * FUNCTION
  382. *
  383. * Transform_Polygon
  384. *
  385. * INPUT
  386. *
  387. * Object - Object
  388. * Trans - Transformation to apply
  389. *
  390. * OUTPUT
  391. *
  392. * Object
  393. *
  394. * RETURNS
  395. *
  396. * AUTHOR
  397. *
  398. * Dieter Bayer
  399. *
  400. * DESCRIPTION
  401. *
  402. * Transform a polygon by transforming all points
  403. * and recalculating the polygon.
  404. *
  405. * CHANGES
  406. *
  407. * May 1994 : Creation.
  408. *
  409. ******************************************************************************/
  410. static void Transform_Polygon(OBJECT *Object, TRANSFORM *Trans)
  411. {
  412. VECTOR N;
  413. POLYGON *Polyg = (POLYGON *)Object;
  414. Compose_Transforms(Polyg->Trans, Trans);
  415. Make_Vector(N, 0.0, 0.0, 1.0);
  416. MTransNormal(Polyg->S_Normal, N, Polyg->Trans);
  417. VNormalizeEq(Polyg->S_Normal);
  418. Compute_Polygon_BBox(Polyg);
  419. }
  420. /*****************************************************************************
  421. *
  422. * FUNCTION
  423. *
  424. * Invert_Polygon
  425. *
  426. * INPUT
  427. *
  428. * Object - Object
  429. *
  430. * OUTPUT
  431. *
  432. * Object
  433. *
  434. * RETURNS
  435. *
  436. * AUTHOR
  437. *
  438. * Dieter Bayer
  439. *
  440. * DESCRIPTION
  441. *
  442. * Invert a polygon.
  443. *
  444. * CHANGES
  445. *
  446. * May 1994 : Creation.
  447. *
  448. ******************************************************************************/
  449. static void Invert_Polygon(OBJECT *Object)
  450. {
  451. }
  452. /*****************************************************************************
  453. *
  454. * FUNCTION
  455. *
  456. * Create_Polygon
  457. *
  458. * INPUT
  459. *
  460. * OUTPUT
  461. *
  462. * RETURNS
  463. *
  464. * POLYGON * - new polygon
  465. *
  466. * AUTHOR
  467. *
  468. * Dieter Bayer
  469. *
  470. * DESCRIPTION
  471. *
  472. * Create a new polygon.
  473. *
  474. * CHANGES
  475. *
  476. * May 1994 : Creation.
  477. *
  478. ******************************************************************************/
  479. POLYGON *Create_Polygon()
  480. {
  481. POLYGON *New;
  482. New = (POLYGON *)POV_MALLOC(sizeof(POLYGON), "polygon");
  483. INIT_OBJECT_FIELDS(New,POLYGON_OBJECT,&Polygon_Methods)
  484. New->Trans = Create_Transform();
  485. Make_Vector(New->S_Normal, 0.0, 0.0, 1.0);
  486. New->Data = NULL;
  487. return (New);
  488. }
  489. /*****************************************************************************
  490. *
  491. * FUNCTION
  492. *
  493. * Copy_Polygon
  494. *
  495. * INPUT
  496. *
  497. * Object - Object
  498. *
  499. * OUTPUT
  500. *
  501. * RETURNS
  502. *
  503. * void * - New polygon
  504. *
  505. * AUTHOR
  506. *
  507. * Dieter Bayer
  508. *
  509. * DESCRIPTION
  510. *
  511. * Copy a polygon structure.
  512. *
  513. * CHANGES
  514. *
  515. * May 1994 : Creation.
  516. *
  517. ******************************************************************************/
  518. static POLYGON *Copy_Polygon(OBJECT *Object)
  519. {
  520. POLYGON *New, *Polyg = (POLYGON *)Object;
  521. New = Create_Polygon ();
  522. /* Get rid of the transformation created in Create_Polygon(). */
  523. Destroy_Transform(New->Trans);
  524. /* Copy polygon. */
  525. *New = *Polyg;
  526. New->Trans = Copy_Transform(Polyg->Trans);
  527. New->Data->References++;
  528. return (New);
  529. }
  530. /*****************************************************************************
  531. *
  532. * FUNCTION
  533. *
  534. * Destroy_Polygon
  535. *
  536. * INPUT
  537. *
  538. * Object - Object
  539. *
  540. * OUTPUT
  541. *
  542. * Object
  543. *
  544. * RETURNS
  545. *
  546. * AUTHOR
  547. *
  548. * Dieter Bayer
  549. *
  550. * DESCRIPTION
  551. *
  552. * Destroy a polygon.
  553. *
  554. * CHANGES
  555. *
  556. * May 1994 : Creation.
  557. *
  558. * Dec 1994 : Fixed memory leakage. [DB]
  559. *
  560. ******************************************************************************/
  561. static void Destroy_Polygon(OBJECT *Object)
  562. {
  563. POLYGON *Polyg = (POLYGON *)Object;
  564. if (--(Polyg->Data->References) == 0)
  565. {
  566. POV_FREE (Polyg->Data->Points);
  567. POV_FREE (Polyg->Data);
  568. }
  569. Destroy_Transform(Polyg->Trans);
  570. POV_FREE (Object);
  571. }
  572. /*****************************************************************************
  573. *
  574. * FUNCTION
  575. *
  576. * Compute_Polygon
  577. *
  578. * INPUT
  579. *
  580. * Polyg - Polygon
  581. * Points - 3D points describing the polygon
  582. *
  583. * OUTPUT
  584. *
  585. * Polyg
  586. *
  587. * RETURNS
  588. *
  589. * AUTHOR
  590. *
  591. * Dieter Bayer
  592. *
  593. * DESCRIPTION
  594. *
  595. * Compute the following things for a given polygon:
  596. *
  597. * - Polygon transformation
  598. *
  599. * - Array of 2d points describing the shape of the polygon
  600. *
  601. * CHANGES
  602. *
  603. * May 1994 : Creation.
  604. *
  605. ******************************************************************************/
  606. void Compute_Polygon(POLYGON *Polyg, int Number, VECTOR *Points)
  607. {
  608. int i;
  609. DBL x, y, z, d;
  610. VECTOR o, u, v, w, N;
  611. MATRIX a, b;
  612. /* Create polygon data. */
  613. if (Polyg->Data == NULL)
  614. {
  615. Polyg->Data = (POLYGON_DATA *)POV_MALLOC(sizeof(POLYGON_DATA), "polygon points");
  616. Polyg->Data->References = 1;
  617. Polyg->Data->Number = Number;
  618. Polyg->Data->Points = (UV_VECT *)POV_MALLOC(Number*sizeof(UV_VECT), "polygon points");
  619. }
  620. else
  621. {
  622. Error("Polygon data already computed.");
  623. }
  624. /* Get polygon's coordinate system (one of the many possible) */
  625. Assign_Vector(o, Points[0]);
  626. /* Find valid, i.e. non-zero u vector. */
  627. for (i = 1; i < Number; i++)
  628. {
  629. VSub(u, Points[i], o);
  630. if (VSumSqr(u) > EPSILON)
  631. {
  632. break;
  633. }
  634. }
  635. if (i == Number)
  636. {
  637. Set_Flag(Polyg, DEGENERATE_FLAG);
  638. Warning(0.0, "Points in polygon are co-linear. Ignoring polygon.\n");
  639. }
  640. /* Find valid, i.e. non-zero v and w vectors. */
  641. for (i++; i < Number; i++)
  642. {
  643. VSub(v, Points[i], o);
  644. VCross(w, u, v);
  645. if ((VSumSqr(v) > EPSILON) && (VSumSqr(w) > EPSILON))
  646. {
  647. break;
  648. }
  649. }
  650. if (i == Number)
  651. {
  652. Set_Flag(Polyg, DEGENERATE_FLAG);
  653. Warning(0.0, "Points in polygon are co-linear. Ignoring polygon.\n");
  654. }
  655. VCross(u, v, w);
  656. VCross(v, w, u);
  657. VNormalize(u, u);
  658. VNormalize(v, v);
  659. VNormalize(w, w);
  660. MIdentity(a);
  661. MIdentity(b);
  662. a[3][0] = -o[X];
  663. a[3][1] = -o[Y];
  664. a[3][2] = -o[Z];
  665. b[0][0] = u[X];
  666. b[1][0] = u[Y];
  667. b[2][0] = u[Z];
  668. b[0][1] = v[X];
  669. b[1][1] = v[Y];
  670. b[2][1] = v[Z];
  671. b[0][2] = w[X];
  672. b[1][2] = w[Y];
  673. b[2][2] = w[Z];
  674. MTimes(Polyg->Trans->inverse, a, b);
  675. MInvers(Polyg->Trans->matrix, Polyg->Trans->inverse);
  676. /* Project points onto the u,v-plane (3D --> 2D) */
  677. for (i = 0; i < Number; i++)
  678. {
  679. x = Points[i][X] - o[X];
  680. y = Points[i][Y] - o[Y];
  681. z = Points[i][Z] - o[Z];
  682. d = x * w[X] + y * w[Y] + z * w[Z];
  683. if (fabs(d) > ZERO_TOLERANCE)
  684. {
  685. Set_Flag(Polyg, DEGENERATE_FLAG);
  686. Warning(0.0, "Points in polygon are not co-planar. Ignoring polygons.\n");
  687. }
  688. Polyg->Data->Points[i][X] = x * u[X] + y * u[Y] + z * u[Z];
  689. Polyg->Data->Points[i][Y] = x * v[X] + y * v[Y] + z * v[Z];
  690. }
  691. Make_Vector(N, 0.0, 0.0, 1.0);
  692. MTransNormal(Polyg->S_Normal, N, Polyg->Trans);
  693. VNormalizeEq(Polyg->S_Normal);
  694. Compute_Polygon_BBox(Polyg);
  695. }
  696. /*****************************************************************************
  697. *
  698. * FUNCTION
  699. *
  700. * Compute_Polygon_BBox
  701. *
  702. * INPUT
  703. *
  704. * Polyg - Polygon
  705. *
  706. * OUTPUT
  707. *
  708. * Polyg
  709. *
  710. * RETURNS
  711. *
  712. * AUTHOR
  713. *
  714. * Dieter Bayer
  715. *
  716. * DESCRIPTION
  717. *
  718. * Calculate the bounding box of a polygon.
  719. *
  720. * CHANGES
  721. *
  722. * May 1994 : Creation.
  723. *
  724. ******************************************************************************/
  725. static void Compute_Polygon_BBox(POLYGON *Polyg)
  726. {
  727. int i;
  728. VECTOR p, Puv, Min, Max;
  729. Min[X] = Min[Y] = Min[Z] = BOUND_HUGE;
  730. Max[X] = Max[Y] = Max[Z] = -BOUND_HUGE;
  731. for (i = 0; i < Polyg->Data->Number; i++)
  732. {
  733. Puv[X] = Polyg->Data->Points[i][X];
  734. Puv[Y] = Polyg->Data->Points[i][Y];
  735. Puv[Z] = 0.0;
  736. MTransPoint(p, Puv, Polyg->Trans);
  737. Min[X] = min(Min[X], p[X]);
  738. Min[Y] = min(Min[Y], p[Y]);
  739. Min[Z] = min(Min[Z], p[Z]);
  740. Max[X] = max(Max[X], p[X]);
  741. Max[Y] = max(Max[Y], p[Y]);
  742. Max[Z] = max(Max[Z], p[Z]);
  743. }
  744. Make_BBox_from_min_max(Polyg->BBox, Min, Max);
  745. if (fabs(Polyg->BBox.Lengths[X]) < Small_Tolerance)
  746. {
  747. Polyg->BBox.Lower_Left[X] -= Small_Tolerance;
  748. Polyg->BBox.Lengths[X] += 2.0 * Small_Tolerance;
  749. }
  750. if (fabs(Polyg->BBox.Lengths[Y]) < Small_Tolerance)
  751. {
  752. Polyg->BBox.Lower_Left[Y] -= Small_Tolerance;
  753. Polyg->BBox.Lengths[Y] += 2.0 * Small_Tolerance;
  754. }
  755. if (fabs(Polyg->BBox.Lengths[Z]) < Small_Tolerance)
  756. {
  757. Polyg->BBox.Lower_Left[Z] -= Small_Tolerance;
  758. Polyg->BBox.Lengths[Z] += 2.0 * Small_Tolerance;
  759. }
  760. }
  761. /*****************************************************************************
  762. *
  763. * FUNCTION
  764. *
  765. * in_polygon
  766. *
  767. * INPUT
  768. *
  769. * Number - Number of points
  770. * Points - Points describing polygon's shape
  771. * u, v - 2D-coordinates of the point to test
  772. *
  773. * OUTPUT
  774. *
  775. * RETURNS
  776. *
  777. * int - TRUE, if inside
  778. *
  779. * AUTHOR
  780. *
  781. * Eric Haines, 3D/Eye Inc, erich@eye.com
  782. *
  783. * DESCRIPTION
  784. *
  785. * ======= Crossings Multiply algorithm ===================================
  786. *
  787. * This version is usually somewhat faster than the original published in
  788. * Graphics Gems IV; by turning the division for testing the X axis crossing
  789. * into a tricky multiplication test this part of the test became faster,
  790. * which had the additional effect of making the test for "both to left or
  791. * both to right" a bit slower for triangles than simply computing the
  792. * intersection each time. The main increase is in triangle testing speed,
  793. * which was about 15% faster; all other polygon complexities were pretty much
  794. * the same as before. On machines where division is very expensive (not the
  795. * case on the HP 9000 series on which I tested) this test should be much
  796. * faster overall than the old code. Your mileage may (in fact, will) vary,
  797. * depending on the machine and the test data, but in general I believe this
  798. * code is both shorter and faster. This test was inspired by unpublished
  799. * Graphics Gems submitted by Joseph Samosky and Mark Haigh-Hutchinson.
  800. * Related work by Samosky is in:
  801. *
  802. * Samosky, Joseph, "SectionView: A system for interactively specifying and
  803. * visualizing sections through three-dimensional medical image data",
  804. * M.S. Thesis, Department of Electrical Engineering and Computer Science,
  805. * Massachusetts Institute of Technology, 1993.
  806. *
  807. *
  808. * Shoot a test ray along +X axis. The strategy is to compare vertex Y values
  809. * to the testing point's Y and quickly discard edges which are entirely to one
  810. * side of the test ray.
  811. *
  812. * CHANGES
  813. *
  814. * -
  815. *
  816. ******************************************************************************/
  817. static int in_polygon(int Number, UV_VECT *Points, DBL u, DBL v)
  818. {
  819. register int i, yflag0, yflag1, inside_flag;
  820. register DBL ty, tx;
  821. register DBL *vtx0, *vtx1, *first;
  822. tx = u;
  823. ty = v;
  824. vtx0 = &Points[0][X];
  825. vtx1 = &Points[1][X];
  826. first = vtx0;
  827. /* get test bit for above/below X axis */
  828. yflag0 = (vtx0[Y] >= ty);
  829. inside_flag = FALSE;
  830. for (i = 1; i < Number; )
  831. {
  832. yflag1 = (vtx1[Y] >= ty);
  833. /*
  834. * Check if endpoints straddle (are on opposite sides) of X axis
  835. * (i.e. the Y's differ); if so, +X ray could intersect this edge.
  836. * The old test also checked whether the endpoints are both to the
  837. * right or to the left of the test point. However, given the faster
  838. * intersection point computation used below, this test was found to
  839. * be a break-even proposition for most polygons and a loser for
  840. * triangles (where 50% or more of the edges which survive this test
  841. * will cross quadrants and so have to have the X intersection computed
  842. * anyway). I credit Joseph Samosky with inspiring me to try dropping
  843. * the "both left or both right" part of my code.
  844. */
  845. if (yflag0 != yflag1)
  846. {
  847. /*
  848. * Check intersection of pgon segment with +X ray.
  849. * Note if >= point's X; if so, the ray hits it.
  850. * The division operation is avoided for the ">=" test by checking
  851. * the sign of the first vertex wrto the test point; idea inspired
  852. * by Joseph Samosky's and Mark Haigh-Hutchinson's different
  853. * polygon inclusion tests.
  854. */
  855. if (((vtx1[Y]-ty) * (vtx0[X]-vtx1[X]) >= (vtx1[X]-tx) * (vtx0[Y]-vtx1[Y])) == yflag1)
  856. {
  857. inside_flag = !inside_flag;
  858. }
  859. }
  860. /* Move to the next pair of vertices, retaining info as possible. */
  861. if ((i < Number-2) && (vtx1[X] == first[X]) && (vtx1[Y] == first[Y]))
  862. {
  863. vtx0 = &Points[++i][X];
  864. vtx1 = &Points[++i][X];
  865. yflag0 = (vtx0[Y] >= ty);
  866. first = vtx0;
  867. }
  868. else
  869. {
  870. vtx0 = vtx1;
  871. vtx1 = &Points[++i][X];
  872. yflag0 = yflag1;
  873. }
  874. }
  875. return(inside_flag);
  876. }