PageRenderTime 54ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/branches/AM-LT/src/plnxtv.c

#
C | 688 lines | 477 code | 82 blank | 129 comment | 157 complexity | 74c8221f40b20aa83bf52ab3375d4711 MD5 | raw file
Possible License(s): LGPL-2.0, BSD-3-Clause-No-Nuclear-License-2014, Apache-2.0, GPL-2.0
  1. /* $Id$
  2. $Log$
  3. Revision 1.4.2.1 2001/04/19 12:31:46 rlaboiss
  4. First merge against MAIN
  5. Revision 1.4 1992/10/12 17:08:07 mjl
  6. Added PL_NEED_SIZE_T define to those files that need to know the value
  7. of (size_t) for non-POSIX systems (in this case the Amiga) that require you
  8. to include <stddef.h> to get it.
  9. * Revision 1.3 1992/09/30 18:25:52 furnish
  10. * Massive cleanup to irradicate garbage code. Almost everything is now
  11. * prototyped correctly. Builds on HPUX, SUNOS (gcc), AIX, and UNICOS.
  12. *
  13. * Revision 1.2 1992/09/29 04:46:10 furnish
  14. * Massive clean up effort to remove support for garbage compilers (K&R).
  15. *
  16. * Revision 1.1 1992/05/20 21:34:40 furnish
  17. * Initial checkin of the whole PLPLOT project.
  18. *
  19. */
  20. /* plnxtv.c
  21. Draw next view of 3d plot.
  22. */
  23. #define PL_NEED_MALLOC
  24. #include "plplot.h"
  25. #include <stdio.h>
  26. #include <stddef.h>
  27. /* Prototypes for static functions */
  28. static void plnxtvhi (PLINT *, PLINT *, PLINT, PLINT);
  29. static void plnxtvlo (PLINT *, PLINT *, PLINT, PLINT);
  30. static void savehipoint (PLINT, PLINT);
  31. static void savelopoint (PLINT, PLINT);
  32. static void swaphiview (void);
  33. static void swaploview (void);
  34. static int plabv (PLINT, PLINT, PLINT, PLINT, PLINT, PLINT);
  35. static void pl3cut (PLINT, PLINT, PLINT, PLINT, PLINT, \
  36. PLINT, PLINT, PLINT, PLINT *, PLINT *);
  37. /*
  38. * Internal constants.
  39. */
  40. #define BINC 50 /* Block size for memory allocation */
  41. static PLINT pl3mode = 0; /* 0 3d solid; 1 mesh plot */
  42. static PLINT pl3upv = 1; /* 1 update view; 0 no update */
  43. static PLINT *oldhiview;
  44. static PLINT *oldloview;
  45. static PLINT *newhiview;
  46. static PLINT *newloview;
  47. static PLINT mhi, xxhi, newhisize;
  48. static PLINT mlo, xxlo, newlosize;
  49. /*----------------------------------------------------------------------*\
  50. * External access routines.
  51. \*----------------------------------------------------------------------*/
  52. void
  53. spl3mode (PLINT mode)
  54. {
  55. pl3mode = mode;
  56. }
  57. void
  58. spl3upv (PLINT upv)
  59. {
  60. pl3upv = upv;
  61. }
  62. void
  63. goldhivw (PLINT **pohivw)
  64. {
  65. *pohivw = oldhiview;
  66. }
  67. void
  68. goldlovw (PLINT **polovw)
  69. {
  70. *polovw = oldloview;
  71. }
  72. /*----------------------------------------------------------------------*\
  73. * void plnxtv (u, v, n, init)
  74. *
  75. * (and utility routines)
  76. *
  77. * Draw the next view of a 3-d plot. The physical coordinates of
  78. * the points for the next view are placed in the n points of arrays
  79. * u and v. The silhouette found so far is stored in the heap as a
  80. * set of m peak points.
  81. *
  82. * These routines dynamically allocate memory for hidden line removal.
  83. * Memory is allocated in blocks of 2*BINC*sizeof(PLINT) bytes. Large
  84. * values of BINC give better performance but also allocate more memory
  85. * than is needed. If your 3D plots are very "spiky" or you are working
  86. * with very large matrices then you will probably want to increase BINC.
  87. \*----------------------------------------------------------------------*/
  88. void
  89. plnxtv (PLINT *u, PLINT *v, PLINT n, PLINT init)
  90. {
  91. plnxtvhi(u, v, n, init);
  92. if (pl3mode)
  93. plnxtvlo(u, v, n, init);
  94. }
  95. static void
  96. plnxtvhi (PLINT *u, PLINT *v, PLINT n, PLINT init)
  97. {
  98. PLINT i, j, first;
  99. PLINT sx1=0, sx2=0, sy1=0, sy2=0;
  100. PLINT su1, su2, sv1, sv2;
  101. PLINT cx, cy, px, py;
  102. PLINT seg, ptold, lstold=0, pthi, pnewhi, newhi, change, ochange=0;
  103. first = 1;
  104. pnewhi = 0;
  105. /* For the initial set of points, just display them and store them as */
  106. /* the peak points. */
  107. if (init == 1) {
  108. /* heap not yet allocated so ... */
  109. if (!(oldhiview = (PLINT *) malloc((size_t)(2 * n * sizeof(PLINT)))))
  110. plexit("Out of memory.");
  111. movphy(u[0], v[0]);
  112. oldhiview[0] = u[0];
  113. oldhiview[1] = v[0];
  114. for (i = 1; i < n; i++) {
  115. draphy(u[i], v[i]);
  116. oldhiview[2 * i] = u[i];
  117. oldhiview[2 * i + 1] = v[i];
  118. }
  119. mhi = n;
  120. return;
  121. }
  122. /* Otherwise, we need to consider hidden-line removal problem. We scan */
  123. /* over the points in both the old (i.e. oldhiview[]) and */
  124. /* new (i.e. u[] and v[]) arrays in order of increasing x coordinate. */
  125. /* At each stage, we find the line segment in the other array (if one */
  126. /* exists) that straddles the x coordinate of the point. We */
  127. /* have to determine if the point lies above or below the line segment, */
  128. /* and to check if the below/above status has changed since the last */
  129. /* point. */
  130. /* If pl3upv = 0 we do not update the view, this is useful for drawing */
  131. /* lines on the graph after we are done plotting points. Hidden line */
  132. /* removal is still done, but the view is not updated. */
  133. xxhi = 0;
  134. i = 0;
  135. j = 0;
  136. if (pl3upv != 0) {
  137. newhisize = 2 * (mhi + BINC);
  138. if (!(newhiview =
  139. (PLINT *) malloc((size_t)(newhisize * sizeof(PLINT))))) {
  140. free((VOID *) oldhiview);
  141. plexit("Out of memory.");
  142. }
  143. }
  144. /* (oldhiview[2*i], oldhiview[2*i]) is the i'th point in the old array */
  145. /* (u[j], v[j]) is the j'th point in the new array */
  146. while (i < mhi || j < n) {
  147. /* The coordinates of the point under consideration are (px,py). */
  148. /* The line segment joins (sx1,sy1) to (sx2,sy2). */
  149. /* "ptold" is true if the point lies in the old array. We set it */
  150. /* by comparing the x coordinates of the i'th old point */
  151. /* and the j'th new point, being careful if we have fallen past */
  152. /* the edges. Having found the point, load up the point and */
  153. /* segment coordinates appropriately. */
  154. ptold = ((oldhiview[2 * i] < u[j] && i < mhi) || j >= n);
  155. if (ptold) {
  156. px = oldhiview[2 * i];
  157. py = oldhiview[2 * i + 1];
  158. seg = j > 0 && j < n;
  159. if (seg) {
  160. sx1 = u[j - 1];
  161. sy1 = v[j - 1];
  162. sx2 = u[j];
  163. sy2 = v[j];
  164. }
  165. }
  166. else {
  167. px = u[j];
  168. py = v[j];
  169. seg = i > 0 && i < mhi;
  170. if (seg) {
  171. sx1 = oldhiview[2 * (i - 1)];
  172. sy1 = oldhiview[2 * (i - 1) + 1];
  173. sx2 = oldhiview[2 * i];
  174. sy2 = oldhiview[2 * i + 1];
  175. }
  176. }
  177. /* Now determine if the point is higher than the segment, using the */
  178. /* logical function "above". We also need to know if it is */
  179. /* the old view or the new view that is higher. "newhi" is set true */
  180. /* if the new view is higher than the old */
  181. if (seg)
  182. pthi = plabv(px, py, sx1, sy1, sx2, sy2);
  183. else
  184. pthi = 1;
  185. newhi = (ptold && !pthi) || (!ptold && pthi);
  186. change = (newhi && !pnewhi) || (!newhi && pnewhi);
  187. /* There is a new intersection point to put in the peak array if the */
  188. /* state of "newhi" changes */
  189. if (first) {
  190. movphy(px, py);
  191. first = 0;
  192. lstold = ptold;
  193. savehipoint(px, py);
  194. pthi = 0;
  195. ochange = 0;
  196. }
  197. else if (change) {
  198. /* Take care of special cases at end of arrays. If pl3upv */
  199. /* is 0 the endpoints are not connected to the old view. */
  200. if (pl3upv == 0 && ((!ptold && j == 0) || (ptold && i == 0))) {
  201. movphy(px, py);
  202. lstold = ptold;
  203. pthi = 0;
  204. ochange = 0;
  205. }
  206. else if (pl3upv == 0 && ((!ptold && i >= mhi) || (ptold && j >= n))) {
  207. movphy(px, py);
  208. lstold = ptold;
  209. pthi = 0;
  210. ochange = 0;
  211. }
  212. /* If pl3upv is not 0 then we do want to connect the current line */
  213. /* with the previous view at the endpoints. */
  214. /* Also find intersection point with old view. */
  215. else {
  216. if (i == 0) {
  217. sx1 = oldhiview[0];
  218. sy1 = -1;
  219. sx2 = oldhiview[0];
  220. sy2 = oldhiview[1];
  221. }
  222. else if (i >= mhi) {
  223. sx1 = oldhiview[2 * (mhi - 1)];
  224. sy1 = oldhiview[2 * (mhi - 1) + 1];
  225. sx2 = oldhiview[2 * (mhi - 1)];
  226. sy2 = -1;
  227. }
  228. else {
  229. sx1 = oldhiview[2 * (i - 1)];
  230. sy1 = oldhiview[2 * (i - 1) + 1];
  231. sx2 = oldhiview[2 * i];
  232. sy2 = oldhiview[2 * i + 1];
  233. }
  234. if (j == 0) {
  235. su1 = u[0];
  236. sv1 = -1;
  237. su2 = u[0];
  238. sv2 = v[0];
  239. }
  240. else if (j >= n) {
  241. su1 = u[n - 1];
  242. sv1 = v[n - 1];
  243. su2 = u[n];
  244. sv2 = -1;
  245. }
  246. else {
  247. su1 = u[j - 1];
  248. sv1 = v[j - 1];
  249. su2 = u[j];
  250. sv2 = v[j];
  251. }
  252. /* Determine the intersection */
  253. pl3cut(sx1, sy1, sx2, sy2, su1, sv1, su2, sv2, &cx, &cy);
  254. if (cx == px && cy == py) {
  255. if (lstold && !ochange)
  256. movphy(px, py);
  257. else
  258. draphy(px, py);
  259. savehipoint(px, py);
  260. lstold = 1;
  261. pthi = 0;
  262. }
  263. else {
  264. if (lstold && !ochange)
  265. movphy(cx, cy);
  266. else
  267. draphy(cx, cy);
  268. lstold = 1;
  269. savehipoint(cx, cy);
  270. }
  271. ochange = 1;
  272. }
  273. }
  274. /* If point is high then draw plot to point and update view. */
  275. if (pthi) {
  276. if (lstold && ptold)
  277. movphy(px, py);
  278. else
  279. draphy(px, py);
  280. savehipoint(px, py);
  281. lstold = ptold;
  282. ochange = 0;
  283. }
  284. pnewhi = newhi;
  285. if (ptold)
  286. i = i + 1;
  287. else
  288. j = j + 1;
  289. }
  290. /* Set oldhiview */
  291. swaphiview();
  292. }
  293. static void
  294. plnxtvlo (PLINT *u, PLINT *v, PLINT n, PLINT init)
  295. {
  296. PLINT i, j, first;
  297. PLINT sx1=0, sx2=0, sy1=0, sy2=0;
  298. PLINT su1, su2, sv1, sv2;
  299. PLINT cx, cy, px, py;
  300. PLINT seg, ptold, lstold=0, ptlo, pnewlo, newlo, change, ochange=0;
  301. first = 1;
  302. pnewlo = 0;
  303. /* For the initial set of points, just display them and store them as */
  304. /* the peak points. */
  305. if (init == 1) {
  306. /* heap not yet allocated so ... */
  307. if (!(oldloview = (PLINT *) malloc((size_t)(2 * n * sizeof(PLINT)))))
  308. plexit("Out of memory.");
  309. movphy(u[0], v[0]);
  310. oldloview[0] = u[0];
  311. oldloview[1] = v[0];
  312. for (i = 1; i < n; i++) {
  313. draphy(u[i], v[i]);
  314. oldloview[2 * i] = u[i];
  315. oldloview[2 * i + 1] = v[i];
  316. }
  317. mlo = n;
  318. return;
  319. }
  320. /* Otherwise, we need to consider hidden-line removal problem. We scan */
  321. /* over the points in both the old (i.e. oldloview[]) and */
  322. /* new (i.e. u[] and v[]) arrays in order of increasing x coordinate. */
  323. /* At each stage, we find the line segment in the other array (if one */
  324. /* exists) that straddles the x coordinate of the point. We */
  325. /* have to determine if the point lies above or below the line segment, */
  326. /* and to check if the below/above status has changed since the last */
  327. /* point. */
  328. /* If pl3upv = 0 we do not update the view, this is useful for drawing */
  329. /* lines on the graph after we are done plotting points. Hidden line */
  330. /* removal is still done, but the view is not updated. */
  331. xxlo = 0;
  332. i = 0;
  333. j = 0;
  334. if (pl3upv != 0) {
  335. newlosize = 2 * (mlo + BINC);
  336. if (!(newloview =
  337. (PLINT *) malloc((size_t)(newlosize * sizeof(PLINT))))) {
  338. free((VOID *) oldloview);
  339. plexit("Out of memory.");
  340. }
  341. }
  342. /* (oldloview[2*i], oldloview[2*i]) is the i'th point in the old array */
  343. /* (u[j], v[j]) is the j'th point in the new array */
  344. while (i < mlo || j < n) {
  345. /* The coordinates of the point under consideration are (px,py). */
  346. /* The line segment joins (sx1,sy1) to (sx2,sy2). */
  347. /* "ptold" is true if the point lies in the old array. We set it */
  348. /* by comparing the x coordinates of the i'th old point */
  349. /* and the j'th new point, being careful if we have fallen past */
  350. /* the edges. Having found the point, load up the point and */
  351. /* segment coordinates appropriately. */
  352. ptold = ((oldloview[2 * i] < u[j] && i < mlo) || j >= n);
  353. if (ptold) {
  354. px = oldloview[2 * i];
  355. py = oldloview[2 * i + 1];
  356. seg = j > 0 && j < n;
  357. if (seg) {
  358. sx1 = u[j - 1];
  359. sy1 = v[j - 1];
  360. sx2 = u[j];
  361. sy2 = v[j];
  362. }
  363. }
  364. else {
  365. px = u[j];
  366. py = v[j];
  367. seg = i > 0 && i < mlo;
  368. if (seg) {
  369. sx1 = oldloview[2 * (i - 1)];
  370. sy1 = oldloview[2 * (i - 1) + 1];
  371. sx2 = oldloview[2 * i];
  372. sy2 = oldloview[2 * i + 1];
  373. }
  374. }
  375. /* Now determine if the point is lower than the segment, using the */
  376. /* logical function "above". We also need to know if it is */
  377. /* the old view or the new view that is lower. "newlo" is set true */
  378. /* if the new view is lower than the old */
  379. if (seg)
  380. ptlo = !plabv(px, py, sx1, sy1, sx2, sy2);
  381. else
  382. ptlo = 1;
  383. newlo = (ptold && !ptlo) || (!ptold && ptlo);
  384. change = (newlo && !pnewlo) || (!newlo && pnewlo);
  385. /* There is a new intersection point to put in the peak array if the */
  386. /* state of "newlo" changes */
  387. if (first) {
  388. movphy(px, py);
  389. first = 0;
  390. lstold = ptold;
  391. savelopoint(px, py);
  392. ptlo = 0;
  393. ochange = 0;
  394. }
  395. else if (change) {
  396. /* Take care of special cases at end of arrays. If pl3upv */
  397. /* is 0 the endpoints are not connected to the old view. */
  398. if (pl3upv == 0 && ((!ptold && j == 0) || (ptold && i == 0))) {
  399. movphy(px, py);
  400. lstold = ptold;
  401. ptlo = 0;
  402. ochange = 0;
  403. }
  404. else if (pl3upv == 0 && ((!ptold && i >= mlo) || (ptold && j >= n))) {
  405. movphy(px, py);
  406. lstold = ptold;
  407. ptlo = 0;
  408. ochange = 0;
  409. }
  410. /* If pl3upv is not 0 then we do want to connect the current line */
  411. /* with the previous view at the endpoints. */
  412. /* Also find intersection point with old view. */
  413. else {
  414. if (i == 0) {
  415. sx1 = oldloview[0];
  416. sy1 = 100000;
  417. sx2 = oldloview[0];
  418. sy2 = oldloview[1];
  419. }
  420. else if (i >= mlo) {
  421. sx1 = oldloview[2 * (mlo - 1)];
  422. sy1 = oldloview[2 * (mlo - 1) + 1];
  423. sx2 = oldloview[2 * (mlo - 1)];
  424. sy2 = 100000;
  425. }
  426. else {
  427. sx1 = oldloview[2 * (i - 1)];
  428. sy1 = oldloview[2 * (i - 1) + 1];
  429. sx2 = oldloview[2 * i];
  430. sy2 = oldloview[2 * i + 1];
  431. }
  432. if (j == 0) {
  433. su1 = u[0];
  434. sv1 = 100000;
  435. su2 = u[0];
  436. sv2 = v[0];
  437. }
  438. else if (j >= n) {
  439. su1 = u[n - 1];
  440. sv1 = v[n - 1];
  441. su2 = u[n];
  442. sv2 = 100000;
  443. }
  444. else {
  445. su1 = u[j - 1];
  446. sv1 = v[j - 1];
  447. su2 = u[j];
  448. sv2 = v[j];
  449. }
  450. /* Determine the intersection */
  451. pl3cut(sx1, sy1, sx2, sy2, su1, sv1, su2, sv2, &cx, &cy);
  452. if (cx == px && cy == py) {
  453. if (lstold && !ochange)
  454. movphy(px, py);
  455. else
  456. draphy(px, py);
  457. savelopoint(px, py);
  458. lstold = 1;
  459. ptlo = 0;
  460. }
  461. else {
  462. if (lstold && !ochange)
  463. movphy(cx, cy);
  464. else
  465. draphy(cx, cy);
  466. lstold = 1;
  467. savelopoint(cx, cy);
  468. }
  469. ochange = 1;
  470. }
  471. }
  472. /* If point is low then draw plot to point and update view. */
  473. if (ptlo) {
  474. if (lstold && ptold)
  475. movphy(px, py);
  476. else
  477. draphy(px, py);
  478. savelopoint(px, py);
  479. lstold = ptold;
  480. ochange = 0;
  481. }
  482. pnewlo = newlo;
  483. if (ptold)
  484. i = i + 1;
  485. else
  486. j = j + 1;
  487. }
  488. /* Set oldloview */
  489. swaploview();
  490. }
  491. static void
  492. savehipoint (PLINT px, PLINT py)
  493. {
  494. PLINT *temp;
  495. if (pl3upv == 0)
  496. return;
  497. if (xxhi >= newhisize) {
  498. /* allocate additional space */
  499. newhisize += 2 * BINC;
  500. if (!(temp = (PLINT *) realloc((VOID *) newhiview,
  501. (size_t)(newhisize * sizeof(PLINT))))) {
  502. free((VOID *) oldhiview);
  503. free((VOID *) newhiview);
  504. plexit("Out of memory.");
  505. }
  506. newhiview = temp;
  507. }
  508. newhiview[xxhi] = px;
  509. xxhi++;
  510. newhiview[xxhi] = py;
  511. xxhi++;
  512. }
  513. static void
  514. savelopoint (PLINT px, PLINT py)
  515. {
  516. PLINT *temp;
  517. if (pl3upv == 0)
  518. return;
  519. if (xxlo >= newlosize) {
  520. /* allocate additional space */
  521. newlosize += 2 * BINC;
  522. if (!(temp = (PLINT *) realloc((VOID *) newloview,
  523. (size_t)(newlosize * sizeof(PLINT))))) {
  524. free((VOID *) oldloview);
  525. free((VOID *) newloview);
  526. plexit("Out of memory.");
  527. }
  528. newloview = temp;
  529. }
  530. newloview[xxlo] = px;
  531. xxlo++;
  532. newloview[xxlo] = py;
  533. xxlo++;
  534. }
  535. static void
  536. swaphiview (void)
  537. {
  538. if (pl3upv != 0) {
  539. mhi = xxhi / 2;
  540. free((VOID *) oldhiview);
  541. oldhiview = newhiview;
  542. }
  543. }
  544. static void
  545. swaploview (void)
  546. {
  547. if (pl3upv != 0) {
  548. mlo = xxlo / 2;
  549. free((VOID *) oldloview);
  550. oldloview = newloview;
  551. }
  552. }
  553. /* Determines if point (px,py) lies above the line joining (sx1,sy1) to */
  554. /* (sx2,sy2). It only works correctly if sx1 <= px <= sx2 */
  555. static int
  556. plabv (PLINT px, PLINT py, PLINT sx1, PLINT sy1, PLINT sx2, PLINT sy2)
  557. {
  558. PLINT above;
  559. if (py >= sy1 && py >= sy2)
  560. above = 1;
  561. else if (py < sy1 && py < sy2)
  562. above = 0;
  563. else if ((PLFLT) (sx2 - sx1) * (py - sy1) >
  564. (PLFLT) (px - sx1) * (sy2 - sy1))
  565. above = 1;
  566. else
  567. above = 0;
  568. return ((PLINT) above);
  569. }
  570. /* Determines the point of intersection (cx,cy) between the line */
  571. /* joining (sx1,sy1) to (sx2,sy2) and the line joining */
  572. /* (su1,sv1) to (su2,sv2). */
  573. static void
  574. pl3cut (PLINT sx1, PLINT sy1, PLINT sx2, PLINT sy2, PLINT su1, PLINT sv1, PLINT su2, PLINT sv2, PLINT *cx, PLINT *cy)
  575. {
  576. PLINT x21, y21, u21, v21, yv1, xu1, a, b;
  577. PLFLT fa, fb;
  578. x21 = sx2 - sx1;
  579. y21 = sy2 - sy1;
  580. u21 = su2 - su1;
  581. v21 = sv2 - sv1;
  582. yv1 = sy1 - sv1;
  583. xu1 = sx1 - su1;
  584. a = x21 * v21 - y21 * u21;
  585. fa = (PLFLT) a;
  586. if (a == 0) {
  587. if (sx2 < su2) {
  588. *cx = sx2;
  589. *cy = sy2;
  590. }
  591. else {
  592. *cx = su2;
  593. *cy = sv2;
  594. }
  595. return;
  596. }
  597. else {
  598. b = yv1 * u21 - xu1 * v21;
  599. fb = (PLFLT) b;
  600. *cx = (PLINT) (sx1 + (fb * x21) / fa + .5);
  601. *cy = (PLINT) (sy1 + (fb * y21) / fa + .5);
  602. }
  603. }