Editor.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:31k
源码类别:

GIS编程

开发平台:

Visual C++

  1. /*===========================================================================*
  2.  *
  3.  * YACME
  4.  * Yet Another ColorMap Editor
  5.  *
  6.  * Patrick BOUCHAUD - 1993
  7.  *                          SGI Switzerland
  8.  *
  9.  *                    Converted to OpenGL using GLUT
  10.  *
  11.  *===========================================================================*/
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include <stdlib.h>
  15. #include <math.h>
  16. #include <GL/glut.h>
  17. #include "mallocbis.h"
  18. /* For portability... */
  19. #undef fsqrt
  20. #define fsqrt(_a)     sqrt(_a)
  21. #define SUP(a,b) ( ((a)>(b)) ? (a) : (b) )
  22. #define INF(a,b) ( ((a)<(b)) ? (a) : (b) )
  23. #define ABS(a) ( ((a)<0) ? -(a) : (a) )
  24. #define POINT 1
  25. #define CURVE 2
  26. #define LEFT_TAN 3
  27. #define RIGHT_TAN 4
  28. #define MANUAL 1
  29. #define CONTINUOUS 2
  30. #define CONSTANT 1
  31. #define LINEAR 2
  32. #define POLYNOMIAL 3
  33. #define TabCmpnt(c,n) TabCmpnt[(n)*4+(c)]
  34. #define MAXNDX (dimlut-1)
  35. #define WINHEIGHT 381
  36. #define WINWIDTH 318
  37. #define LUTRATIO ((float)MAXNDX/255.)
  38. #define LEFT LUTRATIO*(-5.)
  39. #define RIGHT LUTRATIO*(260.)
  40. #define BOTTOM LUTRATIO*(-5.)
  41. #define TOP LUTRATIO*(315.)
  42. #define TANLEN LUTRATIO*(25.)
  43. typedef float Matrix[4][4];
  44. typedef struct {
  45. float x0, y0,
  46. x1, y1;
  47. } Tangente;
  48. typedef struct UserPointStruct {
  49. float x, y;
  50. Tangente tg;
  51. int mode;
  52. float polynome[4];
  53. struct UserPointStruct *next, *last;
  54. } UserPoint;
  55. void ResetCMap(void);
  56. void ApplyCMap(void);
  57. void YACME_makeMenu(void);
  58. extern void invertmat(float from[4][4], float to[4][4]);
  59. static UserPoint *FreePointList = NULL;
  60. #define newPoint( point ) newItem( point, FreePointList, UserPoint )
  61. #define freePoint( point ) freeItem( point, FreePointList )
  62. typedef struct {
  63. int type,
  64. cmpnt,
  65. ndx;
  66. UserPoint *upoint;
  67. } PickObject;
  68. struct {
  69. int leftdown, middledown, rightdown;
  70. } mouse;
  71. void YACME_pick( int mx, int my, PickObject *obj );
  72. void YACME_update( int cmpnt, UserPoint *upoint );
  73. int YACME_get( unsigned long *table );
  74. void DeletePoint( int cmpnt, UserPoint *upoint );
  75. int MovePoint( int, int );
  76. int MoveTangente( int, int, int );
  77. int InsertPoint( PickObject *obj );
  78. void GetPolynome( int mode,
  79. float a0, float b0, float t0,
  80. float a1, float b1, float t1,
  81. float coeff[4] );
  82. void OrthoTransform( int mx, int my, float *x, float *y );
  83. float Polynome4( float x, float *polynome );
  84. static int DrawCurve[4] = { 1, 1, 1, 1, },
  85. modifiedCurve[4] = { 1, 1, 1, 1 },
  86. YACME_refresh = MANUAL,
  87. curCmpnt = 0, curType = 0,
  88. Mousex, Mousey;
  89. static float *TabCmpnt;
  90. static int YACME_switch_menu = 0,
  91. YACME_mode_menu, YACME_edit_menu;
  92. static int YACME_win = 0, W, H , update = 0;
  93. static UserPoint *userPoint[4], *userPointSvg[4], *curPoint = NULL;
  94. static void Redraw( void );
  95. static void Reshape( int, int );
  96. static void Mouse( int, int, int, int );
  97. static void Motion( int, int );
  98. static void Key( unsigned char, int, int );
  99. static void Special( int, int, int );
  100. static void YACME_menuFunc( int );
  101. typedef void (*CallBack)(void);
  102. static CallBack newmapCB, applyCB;
  103. static int dimlut;
  104. /*---------------------------------------------------------------------------*
  105.  * YACME_init
  106.  *---------------------------------------------------------------------------*/
  107. void
  108. YACME_init(
  109. int x, int y, int w, int h,
  110. int dim, float **list,
  111. CallBack newmapFunc, CallBack applyFunc)
  112. {
  113. int i, j;
  114. UserPoint *userpoint;
  115. if (YACME_win) return;
  116. dimlut = dim;
  117. newmapCB = newmapFunc;
  118. applyCB = applyFunc;
  119. if (*list==NULL)
  120. {
  121. *list = TabCmpnt = (float *) malloc( 4*dimlut*sizeof(float) );
  122. for (i=0; i<4; i++)
  123. {
  124. newPoint( userPoint[i] );
  125. userpoint = userPoint[i];
  126. userpoint->mode = POLYNOMIAL;
  127. userpoint->x = 0.;
  128. userpoint->y = 0.;
  129. userpoint->last = NULL;
  130. userpoint->tg.x0 = 0.;
  131. userpoint->tg.y0 = 0.;
  132. userpoint->tg.x1 = TANLEN;
  133. userpoint->tg.y1 = 0.;
  134. newPoint( userpoint->next );
  135. userpoint = userpoint->next;
  136. userpoint->mode = POLYNOMIAL;
  137. userpoint->x = (float)MAXNDX;
  138. userpoint->y = (float)MAXNDX;
  139. userpoint->last = userPoint[i];
  140. userpoint->next = NULL;
  141. userpoint->tg.x0 = (float)(MAXNDX-TANLEN);
  142. userpoint->tg.y0 = (float)MAXNDX;
  143. userpoint->tg.x1 = (float)MAXNDX;
  144. userpoint->tg.y1 = (float)MAXNDX;
  145. }
  146. }
  147. else
  148. {
  149. UserPoint *upoint[4], *lastupoint[4]={0,0,0,0};
  150. TabCmpnt = *list;
  151. for (i=0; i<dim; i++)
  152. {
  153. for (j=0; j<4; j++)
  154. {
  155. if (i==0)
  156. {
  157. newPoint( userPoint[j] );
  158. upoint[j] = userPoint[j];
  159. }
  160. else
  161. {
  162. newPoint( upoint[j]->next );
  163. upoint[j] = upoint[j]->next;
  164. }
  165. upoint[j]->next = NULL;
  166. upoint[j]->last = lastupoint[j];
  167. upoint[j]->mode = LINEAR;
  168. upoint[j]->x = (float)i;
  169. upoint[j]->y = (float)MAXNDX*TabCmpnt(j,i);
  170. if (i==0)
  171. {
  172. upoint[j]->tg.x0 = 0.;
  173. upoint[j]->tg.y0 = 0.;
  174. upoint[j]->tg.x1 = TANLEN;
  175. upoint[j]->tg.y1 = 0.;
  176. }
  177. else
  178. {
  179. float slope = upoint[j]->y - upoint[j]->last->y,
  180. dx = TANLEN/fsqrt(slope*slope + 1),
  181. dy = slope*dx;
  182. upoint[j]->tg.x0 = upoint[j]->x - dx;
  183. upoint[j]->tg.y0 = upoint[j]->y - dy;
  184. upoint[j]->tg.x1 = upoint[j]->x + dx;
  185. upoint[j]->tg.y1 = upoint[j]->y + dy;
  186. }
  187. lastupoint[j] = upoint[j];
  188. }
  189. }
  190. }
  191. /*
  192. TabComponents update
  193. --------------------
  194. */
  195. for (i=0; i<4; i++)
  196. {
  197. for (userpoint=userPoint[i]; userpoint!=NULL; userpoint=userpoint->next)
  198. YACME_update( i, userpoint );
  199. }
  200. ApplyCMap();
  201. if (!YACME_win)
  202. {
  203. glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
  204. glutInitWindowPosition( x, y );
  205. glutInitWindowSize( w, h );
  206. YACME_win = glutCreateWindow( "LUT editor" );
  207. glutDisplayFunc( Redraw );
  208. glutReshapeFunc( Reshape );
  209. glutMouseFunc( Mouse );
  210. glutMotionFunc( Motion );
  211. glutPassiveMotionFunc( Motion );
  212. glutSpecialFunc( Special );
  213. glutKeyboardFunc( Key );
  214. glMatrixMode( GL_PROJECTION );
  215. glLoadIdentity();
  216. glOrtho( LEFT, RIGHT, BOTTOM, TOP, -1., 1. );
  217. glClearColor( 0.66, 0.66, 0.66, 1. );
  218. glClear( GL_COLOR_BUFFER_BIT );
  219. glShadeModel( GL_FLAT );
  220. glutSwapBuffers();
  221. YACME_makeMenu();
  222. }
  223. }
  224. /*---------------------------------------------------------------------------*
  225.  * Key
  226.  *---------------------------------------------------------------------------*/
  227. /* ARGSUSED1 */
  228. static void
  229. Key( unsigned char key, int x, int y )
  230. {
  231. UserPoint *previousPoint;
  232. switch (key)
  233. {
  234. case 27: /* Escape */
  235. exit(0);
  236. break;
  237. case 127: /* BackSpace */
  238. case 8: /* Delete */
  239. if (!curPoint) return;
  240. previousPoint = (curPoint->last ? curPoint->last : userPoint[curCmpnt]);
  241. DeletePoint( curCmpnt, curPoint );
  242. modifiedCurve[curCmpnt] = 1;
  243. update = 1;
  244. curPoint = previousPoint;
  245. break;
  246. }
  247. glutPostRedisplay();
  248. }
  249. /*---------------------------------------------------------------------------*
  250.  *      Special
  251.  *---------------------------------------------------------------------------*/
  252. /* ARGSUSED1 */
  253. static void
  254. Special( int key, int xx, int yy )
  255. {
  256. int x, y, minx, maxx;
  257. float dx, dy;
  258. if (curPoint == NULL ) return;
  259. if (curPoint->next == NULL) return;
  260. if (curPoint->last == NULL) return;
  261. x = (int)curPoint->x;
  262. y = (int)curPoint->y;
  263. minx = (int)curPoint->last->x; minx++;
  264. maxx = (int)curPoint->next->x; maxx--;
  265. switch (key)
  266. {
  267. case GLUT_KEY_LEFT:
  268. if (x > minx) x--;
  269. break;
  270. case GLUT_KEY_RIGHT:
  271. if (x < maxx) x++;
  272. break;
  273. case GLUT_KEY_UP:
  274. if (y < MAXNDX) y++;
  275. break;
  276. case GLUT_KEY_DOWN:
  277. if (y > 0) y--;
  278. break;
  279. }
  280. dx = (float)x - curPoint->x;
  281. curPoint->x += dx;
  282. curPoint->tg.x0 += dx;
  283. curPoint->tg.x1 += dx;
  284. dy = (float)y - curPoint->y;
  285. curPoint->y = y;
  286. curPoint->tg.y0 += dy;
  287. curPoint->tg.y1 += dy;
  288. update = 1;
  289. glutPostRedisplay();
  290. }
  291. /*---------------------------------------------------------------------------*
  292.  * Reshape
  293.  *---------------------------------------------------------------------------*/
  294. static void
  295. Reshape( int w, int h )
  296. {
  297. glViewport( 0, 0, w, h );
  298. W = w;
  299. H = h;
  300. glutPostRedisplay();
  301. }
  302. /*---------------------------------------------------------------------------*
  303.  * Mouse
  304.  *---------------------------------------------------------------------------*/
  305. static void
  306. Mouse( int button, int state, int x, int y )
  307. {
  308. PickObject object;
  309. y = H-y;
  310. switch (button)
  311. {
  312. case GLUT_RIGHT_BUTTON:
  313. mouse.rightdown = (state==GLUT_DOWN);
  314. break;
  315. case GLUT_MIDDLE_BUTTON:
  316. mouse.middledown = (state==GLUT_DOWN);
  317. break;
  318. case GLUT_LEFT_BUTTON:
  319. mouse.leftdown = (state==GLUT_DOWN);
  320. if (mouse.leftdown)
  321. {
  322. YACME_pick( x, y, &object );
  323. curType = object.type;
  324. switch ( object.type )
  325. {
  326. case CURVE:
  327. if ((curType = InsertPoint( &object ) != 0))
  328. {
  329. curPoint = object.upoint;
  330. curCmpnt = object.cmpnt;
  331. }
  332. else curPoint = NULL;
  333. break;
  334. case POINT:
  335. case LEFT_TAN:
  336. case RIGHT_TAN:
  337. curPoint = object.upoint;
  338. curCmpnt = object.cmpnt;
  339. break;
  340. default:
  341. curPoint = NULL;
  342. }
  343. break;
  344. }
  345. }
  346. glutPostRedisplay();
  347. }
  348. /*---------------------------------------------------------------------------*
  349.  * Motion
  350.  *---------------------------------------------------------------------------*/
  351. static void
  352. Motion( int x, int y )
  353. {
  354. Mousex = x;
  355. Mousey = H-y;
  356. if (mouse.leftdown)
  357. {
  358. switch (curType)
  359. {
  360. case POINT:
  361. update = MovePoint( Mousex, Mousey );
  362. break;
  363. case LEFT_TAN:
  364. update = MoveTangente( -1, Mousex, Mousey );
  365. break;
  366. case RIGHT_TAN:
  367. update = MoveTangente( 1, Mousex, Mousey );
  368. break;
  369. }
  370. }
  371. glutPostRedisplay();
  372. }
  373. /*---------------------------------------------------------------------------*
  374.  * YACME_makeMenu
  375.  *---------------------------------------------------------------------------*/
  376. #define CONTINUOUS_ITEM 5
  377. #define MANUAL_ITEM 4
  378. #define APPLY_ITEM 3
  379. #define RESET_ITEM 2
  380. #define CLOSE_ITEM 1
  381. #define RED_ITEM 10
  382. #define GREEN_ITEM 11
  383. #define BLUE_ITEM 12
  384. #define ALPHA_ITEM 13
  385. #define CONSTANT_ITEM 22
  386. #define LINEAR_ITEM 21
  387. #define POLYNOM_ITEM 20
  388. #define EDIT_RED_ITEM 30
  389. #define EDIT_GREEN_ITEM 31
  390. #define EDIT_BLUE_ITEM 32
  391. #define EDIT_ALPHA_ITEM 33
  392. void
  393. YACME_makeMenu(void)
  394. {
  395. YACME_edit_menu = glutCreateMenu( YACME_menuFunc );
  396. glutAddMenuEntry( "red", EDIT_RED_ITEM );
  397. glutAddMenuEntry( "green", EDIT_GREEN_ITEM );
  398. glutAddMenuEntry( "blue", EDIT_BLUE_ITEM );
  399. glutAddMenuEntry( "alpha", EDIT_ALPHA_ITEM );
  400. YACME_mode_menu = glutCreateMenu( YACME_menuFunc );
  401. glutAddMenuEntry( "Constant  ", CONSTANT_ITEM );
  402. glutAddMenuEntry( "Linear    ", LINEAR_ITEM );
  403. glutAddMenuEntry( "Polynomial", POLYNOM_ITEM );
  404. YACME_switch_menu = glutCreateMenu( YACME_menuFunc );
  405. glutAddMenuEntry( "Red    on", RED_ITEM );
  406. glutAddMenuEntry( "Green on", GREEN_ITEM );
  407. glutAddMenuEntry( "Blue   on", BLUE_ITEM );
  408. glutAddMenuEntry( "Alpha on", ALPHA_ITEM );
  409. glutCreateMenu( YACME_menuFunc );
  410. glutAddMenuEntry( "Manual    ", MANUAL_ITEM );
  411. glutAddMenuEntry( "Apply", APPLY_ITEM );
  412. glutAddMenuEntry( "Reset", RESET_ITEM );
  413. glutAddMenuEntry( "Close", CLOSE_ITEM );
  414. glutAddSubMenu(   "Mode... ", YACME_mode_menu );
  415. glutAddSubMenu(   "Switch... ", YACME_switch_menu );
  416. glutAddSubMenu(   "Edit... ", YACME_edit_menu );
  417. glutAttachMenu( GLUT_RIGHT_BUTTON );
  418. }
  419. /*---------------------------------------------------------------------------*
  420.  * YACME_menuFunc
  421.  *---------------------------------------------------------------------------*/
  422. static void
  423. YACME_menuFunc( int item )
  424. {
  425. switch( item )
  426. {
  427. case CLOSE_ITEM:
  428. break;
  429. case RESET_ITEM:
  430. if (applyCB) (*applyCB)();
  431. else if (newmapCB) (*newmapCB)();
  432. ResetCMap();
  433. curPoint = NULL;
  434. break;
  435. case APPLY_ITEM:
  436. if (applyCB) (*applyCB)();
  437. else if (newmapCB) (*newmapCB)();
  438. ApplyCMap();
  439. break;
  440. case MANUAL_ITEM: /* switch to continuous */
  441. glutChangeToMenuEntry( 1, "Continuous", CONTINUOUS_ITEM );
  442. YACME_refresh = CONTINUOUS;
  443. break;
  444. case CONTINUOUS_ITEM: /* switch to manual */
  445. glutChangeToMenuEntry( 1, "Manual    ", MANUAL_ITEM );
  446. if (newmapCB) (*newmapCB)();
  447. ApplyCMap();
  448. YACME_refresh = MANUAL;
  449. break;
  450. case RED_ITEM:
  451. DrawCurve[0] = !DrawCurve[0];
  452. if (DrawCurve[0])
  453. glutChangeToMenuEntry( 1, "Red     on", RED_ITEM );
  454. else
  455. glutChangeToMenuEntry( 1, "Red    off", RED_ITEM );
  456. curPoint = NULL;
  457. break;
  458. case GREEN_ITEM:
  459. DrawCurve[1] = !DrawCurve[1];
  460. if (DrawCurve[1])
  461. glutChangeToMenuEntry( 2, "Green on", GREEN_ITEM );
  462. else
  463. glutChangeToMenuEntry( 2, "Green off", GREEN_ITEM );
  464. curPoint = NULL;
  465. break;
  466. case BLUE_ITEM:
  467. DrawCurve[2] = !DrawCurve[2];
  468. if (DrawCurve[2])
  469. glutChangeToMenuEntry( 3, "Blue   on", BLUE_ITEM );
  470. else
  471. glutChangeToMenuEntry( 3, "Blue   off", BLUE_ITEM );
  472. curPoint = NULL;
  473. break;
  474. case ALPHA_ITEM:
  475. DrawCurve[3] = !DrawCurve[3];
  476. if (DrawCurve[3])
  477. glutChangeToMenuEntry( 4, "Alpha on", ALPHA_ITEM );
  478. else
  479. glutChangeToMenuEntry( 4, "Alpha off", ALPHA_ITEM );
  480. curPoint = NULL;
  481. break;
  482. case CONSTANT_ITEM:
  483. if (curPoint != NULL)
  484. {
  485. update = 1;
  486. curPoint->mode = CONSTANT;
  487. }
  488. break;
  489. case LINEAR_ITEM:
  490. if (curPoint != NULL)
  491. {
  492. update = 1;
  493. curPoint->mode = LINEAR;
  494. }
  495. break;
  496. case POLYNOM_ITEM:
  497. if (curPoint != NULL)
  498. {
  499. update = 1;
  500. curPoint->mode = POLYNOMIAL;
  501. }
  502. break;
  503. case EDIT_RED_ITEM:
  504. case EDIT_GREEN_ITEM:
  505. case EDIT_BLUE_ITEM:
  506. case EDIT_ALPHA_ITEM:
  507. curCmpnt = item-30;
  508. curPoint = userPoint[curCmpnt];
  509. break;
  510. }
  511. glutPostRedisplay();
  512. }
  513. /*---------------------------------------------------------------------------*
  514.  * output
  515.  *---------------------------------------------------------------------------*/
  516. static void
  517. output( float x, float y, char *string )
  518. {
  519. int len, i;
  520. glRasterPos2f(x, y);
  521. len = (int) strlen(string);
  522. for (i = 0; i < len; i++)
  523. {
  524. glutBitmapCharacter(GLUT_BITMAP_8_BY_13, string[i]);
  525. }
  526. }
  527. /*---------------------------------------------------------------------------*
  528.  * Redraw
  529.  *---------------------------------------------------------------------------*/
  530. static void
  531. Redraw( void )
  532. {
  533. int i, j, ndx, cmpnt, priority[4];
  534. Tangente *tg;
  535. UserPoint *upoint;
  536. char string[256];
  537. if (update)
  538. {
  539. modifiedCurve[curCmpnt] = 1;
  540. YACME_update( curCmpnt, curPoint );
  541. if ( newmapCB && (YACME_refresh == CONTINUOUS))
  542. (*newmapCB)();
  543. update = 0;
  544. }
  545. glClear( GL_COLOR_BUFFER_BIT );
  546. /*
  547. Barettes representant la table des couleurs
  548. -------------------------------------------
  549. */
  550. glBegin( GL_TRIANGLE_STRIP );
  551. glColor3f(TabCmpnt(0,0), TabCmpnt(1,0), TabCmpnt(2,0));
  552. glVertex2f( 0., 270.*LUTRATIO );
  553. glVertex2f( 0., 310.*LUTRATIO );
  554. glVertex2f( .5, 270.*LUTRATIO );
  555. glVertex2f( .5, 310.*LUTRATIO );
  556. glEnd();
  557. for ( i=1; i<MAXNDX; i++ )
  558. {
  559. float x=(float)i - .5;
  560. glBegin( GL_TRIANGLE_STRIP );
  561. glColor3f(TabCmpnt(0,i), TabCmpnt(1,i), TabCmpnt(2,i));
  562. glVertex2f( x, 270.*LUTRATIO );
  563.    glVertex2f( x, 310.*LUTRATIO );
  564. glVertex2f( x+1., 270.*LUTRATIO );
  565. glVertex2f( x+1., 310.*LUTRATIO );
  566. glEnd();
  567.   }
  568. glBegin( GL_TRIANGLE_STRIP );
  569. glColor3f(TabCmpnt(0,MAXNDX), TabCmpnt(1,MAXNDX), TabCmpnt(2,MAXNDX));
  570. glVertex2f( (float)MAXNDX-.5, 270.*LUTRATIO );
  571. glVertex2f( (float)MAXNDX-.5, 310.*LUTRATIO );
  572. glVertex2f( (float)MAXNDX, 270.*LUTRATIO );
  573. glVertex2f( (float)MAXNDX, 310.*LUTRATIO );
  574. glEnd();
  575. /*
  576. Graphe y = cpste(x)
  577. -------------------
  578. */ 
  579. glColor3f(0.,0.,0.);
  580. glBegin( GL_TRIANGLE_STRIP );
  581. glVertex2f( 0., 0. );
  582. glVertex2f( (float) MAXNDX, 0. );
  583. glVertex2f( 0., (float) MAXNDX );
  584. glVertex2f( (float) MAXNDX, (float) MAXNDX );
  585. glEnd();
  586. /*
  587. Curves y = cpste(x)
  588. --------------------
  589. */
  590. for ( i=0; i<curCmpnt; i++)
  591. {
  592. priority[i] = i;
  593. }
  594. for ( i=curCmpnt+1; i<4; i++ ) {
  595. priority[i-1] = i;
  596. }
  597. priority[3] = curCmpnt;
  598.  
  599. cmpnt = priority[0];
  600. for ( i=0; i<4; i++, cmpnt=priority[i] ) if ( DrawCurve[cmpnt] )
  601. {
  602. switch (cmpnt)
  603. {
  604. case 3: glColor3f(1.,1.,1.); break;
  605. case 2: glColor3f(0.,0.,1.); break;
  606. case 1: glColor3f(0.,1.,0.); break;
  607. case 0: glColor3f(1.,0.,0.); break;
  608. }
  609. for ( j=0; j<MAXNDX; j++ )
  610. {
  611. glBegin( GL_LINES );
  612. glVertex2f( (float)j, (float)MAXNDX*TabCmpnt(cmpnt,j) );
  613. glVertex2f( (float)(j+1), (float)MAXNDX*TabCmpnt(cmpnt,j+1) );
  614. glEnd();
  615. }
  616. }
  617. if ( curPoint != NULL )
  618. {
  619. float h;
  620. /*
  621. user defined points
  622. -------------------
  623. */
  624. upoint = userPoint[curCmpnt];
  625. do {
  626. /*
  627. Point
  628. -----
  629. */
  630. #define DIMPOINT (2.*LUTRATIO)
  631. glBegin( GL_TRIANGLE_STRIP );
  632. glVertex2f( upoint->x-DIMPOINT, upoint->y-DIMPOINT );
  633. glVertex2f( upoint->x-DIMPOINT, upoint->y+DIMPOINT );
  634. glVertex2f( upoint->x+DIMPOINT, upoint->y-DIMPOINT );
  635. glVertex2f( upoint->x+DIMPOINT, upoint->y+DIMPOINT );
  636. glEnd();
  637. /*
  638. Tangente
  639. --------
  640. */
  641. tg = &upoint->tg;
  642. if (upoint->last ? upoint->last->mode == POLYNOMIAL : 0)
  643. {
  644. glBegin( GL_LINES );
  645. glVertex2f( tg->x0, tg->y0 );
  646. glVertex2f( upoint->x, upoint->y );
  647. glEnd();
  648. glBegin( GL_LINE_LOOP );
  649. glVertex2f( tg->x0-DIMPOINT, tg->y0-DIMPOINT );
  650. glVertex2f( tg->x0-DIMPOINT, tg->y0+DIMPOINT );
  651. glVertex2f( tg->x0+DIMPOINT, tg->y0+DIMPOINT );
  652. glVertex2f( tg->x0+DIMPOINT, tg->y0-DIMPOINT );
  653. glEnd();
  654. }
  655. if (upoint->mode == POLYNOMIAL)
  656. {
  657. glBegin( GL_LINES );
  658. glVertex2f( upoint->x, upoint->y );
  659. glVertex2f( tg->x1, tg->y1 );
  660. glEnd();
  661. glBegin( GL_LINE_LOOP );
  662. glVertex2f( tg->x1-DIMPOINT, tg->y1-DIMPOINT );
  663. glVertex2f( tg->x1-DIMPOINT, tg->y1+DIMPOINT );
  664. glVertex2f( tg->x1+DIMPOINT, tg->y1+DIMPOINT );
  665. glVertex2f( tg->x1+DIMPOINT, tg->y1-DIMPOINT );
  666. glEnd();
  667. }
  668. } while ( (upoint=upoint->next) != NULL );
  669. /*
  670. Highlight current point
  671. -----------------------
  672. */
  673. ndx = curPoint->x;
  674. h = curPoint->y;
  675. switch (curCmpnt)
  676. {
  677. case 3: glColor3f(1.,1.,1.); break;
  678. case 2: glColor3f(0.,0.,1.); break;
  679. case 1: glColor3f(0.,1.,0.); break;
  680. case 0: glColor3f(1.,0.,0.); break;
  681. }
  682. glBegin( GL_LINE_LOOP );
  683. glVertex2f( (float)ndx-2.*DIMPOINT, h-2.*DIMPOINT );
  684. glVertex2f( (float)ndx-2.*DIMPOINT, h+2.*DIMPOINT );
  685. glVertex2f( (float)ndx+2.*DIMPOINT, h+2.*DIMPOINT );
  686. glVertex2f( (float)ndx+2.*DIMPOINT, h-2.*DIMPOINT );
  687. glEnd();
  688. }
  689. else
  690. {
  691. float x, y;
  692. OrthoTransform( Mousex, Mousey, &x, &y );
  693. ndx = (int) SUP( INF(x,(float)MAXNDX), 0 );
  694. }
  695. /*
  696. Coordinates text string
  697. -----------------------
  698. */
  699. glColor3f( 0., 0., 0. );
  700. sprintf( string,
  701. "%.5d: rgba %.3f %.3f %.3f %.3f",
  702. ndx,
  703. TabCmpnt(0,ndx),
  704. TabCmpnt(1,ndx),
  705. TabCmpnt(2,ndx),
  706. TabCmpnt(3,ndx)
  707. );
  708. output( LUTRATIO, 257.*LUTRATIO, string );
  709. glutSwapBuffers();
  710. }
  711. /*---------------------------------------------------------------------------*
  712.  * YACME_pick
  713.  *---------------------------------------------------------------------------*/
  714. void
  715. YACME_pick( int mousex, int mousey, PickObject *obj )
  716. {
  717.  int cmpnt, i, priority[4];
  718.  float x, y, val;
  719.  Tangente *tg;
  720.  UserPoint *upoint;
  721.  float pickrad;
  722.  obj->type = -1;
  723.  OrthoTransform( mousex, mousey, &x, &y );
  724. /*
  725.  On travaille en priorite sur les objets definis par l'utilisateur
  726.  -----------------------------------------------------------------
  727. */
  728.  for ( i=0; i<curCmpnt; i++) {
  729. priority[i] = i;
  730.  }
  731.  for ( i=curCmpnt+1; i<4; i++ ) {
  732. priority[i-1] = i;
  733.  }
  734.  priority[3] = curCmpnt;
  735.  
  736.  pickrad = 3.*LUTRATIO;
  737.  cmpnt = priority[3];
  738.  for ( i=3; i>=0; i--, cmpnt=priority[i] ) if ( DrawCurve[cmpnt] ) {
  739. upoint = userPoint[cmpnt];
  740. while ( upoint != NULL ) {
  741. /*
  742. On cherche le POINT
  743. */
  744. if ( ABS(y-upoint->y) < pickrad && ABS(x-upoint->x) < pickrad ) {
  745. obj->upoint = upoint;
  746. obj->cmpnt = cmpnt;
  747. obj->type = POINT;
  748. return;
  749. }
  750. /*
  751. On cherche la demi-tangente GAUCHE
  752. */
  753. tg = &upoint->tg;
  754. if ( ABS(x-tg->x0) < pickrad && ABS(y-tg->y0) < pickrad ) {
  755. obj->upoint = upoint;
  756. obj->cmpnt = cmpnt;
  757. obj->type = LEFT_TAN;
  758. return;
  759. }
  760. /*
  761. On cherche la demi-tangente DROITE
  762. */
  763. if ( ABS(x-tg->x1) < pickrad && ABS(y-tg->y1) < pickrad ) {
  764. obj->upoint = upoint;
  765. obj->cmpnt = cmpnt;
  766. obj->type = RIGHT_TAN;
  767. return;
  768. }
  769. upoint = upoint->next;
  770. }
  771. /*
  772. Puis on cherche les coordonnees sur la CURVE
  773. (On considere la precision suffisante pour le picking suivant l'axe X)
  774. Remarque : on ne sort pas en ce cas, car la priorite est sur les objets
  775. utilisateurs.
  776. */
  777. upoint = userPoint[cmpnt];
  778. while ( upoint->next->x < x ) {
  779. upoint = upoint->next;
  780. if ( upoint->next == NULL ) return;
  781. }
  782. val = INF( SUP( Polynome4(x,upoint->polynome), 0.), (float)MAXNDX );
  783. if ( ABS(y-val) < pickrad ) {
  784. obj->cmpnt = cmpnt;
  785. obj->ndx = ((x-(int)x)<.5) ? (int)x : (int)x+1;
  786. obj->type = CURVE;
  787. return;
  788. }
  789.  }
  790. }
  791. /*---------------------------------------------------------------------------*
  792.  * YACME_update
  793.  *---------------------------------------------------------------------------*/
  794. void
  795. YACME_update( int cmpnt, UserPoint *upoint )
  796. {
  797.  int i;
  798.  float val, t0, t1;
  799.  Tangente *tg;
  800.  tg = &upoint->tg;
  801.  if ( tg->x1 != tg->x0 ) {
  802. t0 = (tg->y1-tg->y0) / (tg->x1-tg->x0);
  803.  } else {
  804. t0 = (tg->y1-tg->y0)*10000.;
  805.  }
  806.  TabCmpnt(cmpnt,(int) upoint->x) = upoint->y/(float)MAXNDX;
  807.  if ( upoint->last != NULL ) {
  808. tg = &upoint->last->tg;
  809. if ( tg->x1 != tg->x0 ) {
  810. t1 = (tg->y1-tg->y0) / (tg->x1-tg->x0);
  811. } else {
  812. t1 = (tg->y1-tg->y0)*10000.;
  813. }
  814. GetPolynome(
  815. upoint->last->mode,
  816. upoint->last->x,
  817. upoint->last->y,
  818. t1,
  819. upoint->x,
  820. upoint->y,
  821. t0,
  822. upoint->last->polynome
  823. );
  824. for ( i=1+(int) upoint->last->x; i<(int) upoint->x; i++ ) {
  825. val = Polynome4((float) i, upoint->last->polynome)/(float)MAXNDX;
  826. TabCmpnt(cmpnt,i) = INF( SUP(val,0.), 1. );
  827. }
  828.  }
  829.  if ( upoint->next != NULL ) {
  830. tg = &upoint->next->tg;
  831. if ( tg->x1 != tg->x0 ) {
  832. t1 = (tg->y1-tg->y0) / (tg->x1-tg->x0);
  833. } else {
  834. t1 = (tg->y1-tg->y0)*10000.;
  835. }
  836. GetPolynome(
  837. upoint->mode,
  838. upoint->x,
  839. upoint->y,
  840. t0,
  841. upoint->next->x,
  842. upoint->next->y,
  843. t1,
  844. upoint->polynome
  845. );
  846. for ( i=1+(int) upoint->x; i<(int) upoint->next->x; i++ ) {
  847. val = Polynome4( (float) i, upoint->polynome )/(float)MAXNDX;
  848. TabCmpnt(cmpnt,i) = INF( SUP(val,0.), 1. );
  849. }
  850. TabCmpnt(cmpnt,(int) upoint->next->x) = upoint->next->y/(float)MAXNDX;
  851.  }
  852. }
  853. /*---------------------------------------------------------------------------*
  854.  * freePointList
  855.  *---------------------------------------------------------------------------*/
  856. static void
  857. freePointList( UserPoint *upoint )
  858. {
  859. while (upoint != NULL)
  860. {
  861. UserPoint *unext = upoint->next;
  862. freePoint( upoint );
  863. upoint = unext;
  864. }
  865. }
  866. /*---------------------------------------------------------------------------*
  867.  * clonePointList
  868.  *---------------------------------------------------------------------------*/
  869. static UserPoint *
  870. clonePointList( UserPoint *base )
  871. {
  872. UserPoint *clone, *upoint;
  873. if (base == NULL) return NULL;
  874. newPoint( clone );
  875. upoint = clone;
  876. memcpy( upoint, base, sizeof(UserPoint) );
  877. upoint->last = NULL;
  878. upoint->next = NULL;
  879. while (base->next != NULL)
  880. {
  881. base = base->next;
  882. newPoint( upoint->next );
  883. memcpy( upoint->next, base, sizeof(UserPoint) );
  884. upoint->next->last = upoint;
  885. upoint->next->next = NULL;
  886. upoint = upoint->next;
  887. }
  888. return clone;
  889. }
  890. /*---------------------------------------------------------------------------*
  891.  * ApplyCMap
  892.  *---------------------------------------------------------------------------*/
  893. void
  894. ApplyCMap(void)
  895. {
  896. int i;
  897. for (i=0; i<4; i++) if ( modifiedCurve[i] )
  898. {
  899. freePointList( userPointSvg[i] );
  900. userPointSvg[i] = clonePointList( userPoint[i] );
  901. modifiedCurve[i] = 0;
  902. }
  903. }
  904. /*---------------------------------------------------------------------------*
  905.  * ResetCMap
  906.  *---------------------------------------------------------------------------*/
  907. void
  908. ResetCMap(void)
  909. {
  910. int i;
  911. UserPoint *upoint;
  912. for (i=0; i<4; i++) if ( modifiedCurve[i] )
  913. {
  914. freePointList( userPoint[i] );
  915. userPoint[i] = clonePointList( userPointSvg[i] );
  916. modifiedCurve[i] = 0;
  917. for (upoint=userPoint[i]; upoint!=NULL; upoint=upoint->next )
  918. YACME_update( i, upoint );
  919. }
  920. }
  921. /*---------------------------------------------------------------------------*
  922.  * InsertPoint
  923.  *---------------------------------------------------------------------------*/
  924. int
  925. InsertPoint( PickObject *obj )
  926. {
  927.  float dx, dy, slope, coeff[4];
  928.  int i;
  929.  Tangente *tg;
  930.  UserPoint *upoint, *userpoint;
  931.  upoint = userPoint[obj->cmpnt];
  932.  while ( (int) upoint->next->x <= obj->ndx ) {
  933. upoint = upoint->next;
  934. if ( upoint->next == NULL ) return 0;
  935.  }
  936.  if ( (int) upoint->x == obj->ndx ) {
  937. obj->upoint = upoint;
  938. return POINT;
  939.  }
  940.  newPoint( userpoint );
  941.  userpoint->x = (float) obj->ndx;
  942.  userpoint->y = Polynome4( obj->ndx, upoint->polynome );
  943.  userpoint->y = SUP( INF(userpoint->y, (float)MAXNDX), 0. );
  944.  userpoint->mode = upoint->mode;
  945.  for ( i=0; i<4; i++ ) {
  946. userpoint->polynome[i] = upoint->polynome[i];
  947.  }
  948.  userpoint->next = upoint->next;
  949.  userpoint->last = upoint;
  950.  upoint->next = userpoint;
  951.  userpoint->next->last = userpoint;
  952. /*
  953.  calcul de slope = P'(index)
  954.  ---------------------------
  955. */
  956.  if ( userpoint->y == (float)MAXNDX || userpoint->y == 0. ) {
  957. dx = 25.;
  958. dy = 0.;
  959.  } else {
  960. coeff[0] = userpoint->polynome[0]*3.;
  961. coeff[1] = userpoint->polynome[1]*2.;
  962. coeff[2] = userpoint->polynome[2];
  963. slope = coeff[0];
  964. for (i=1; i<3; i++) {
  965. slope *= (float) obj->ndx;
  966. slope += coeff[i];
  967. }
  968. /*
  969. Rappel :
  970. cos( arctg(x) ) = 1/sqr( 1 + x^2 );
  971. sin( arctg(x) ) = |x|/sqr( 1 + x^2 );
  972. */
  973. dx = 25. / fsqrt( slope*slope + 1. );
  974. dy = dx*slope;
  975.  }
  976.  dx *= LUTRATIO;
  977.  dy *= LUTRATIO;
  978.  tg = &userpoint->tg;
  979.  tg->x0 = userpoint->x - dx;
  980.  tg->x1 = userpoint->x + dx;
  981.  tg->y0 = userpoint->y - dy;
  982.  tg->y1 = userpoint->y + dy;
  983.  obj->upoint = userpoint;
  984.  return POINT;
  985. }
  986. /*---------------------------------------------------------------------------*
  987.  * DeletePoint
  988.  *---------------------------------------------------------------------------*/
  989. void
  990. DeletePoint( int cmpnt, UserPoint *upoint )
  991. {
  992. if ( upoint == NULL || upoint->last == NULL || upoint->next == NULL )
  993. return;
  994. upoint->last->next = upoint->next;
  995. upoint->next->last = upoint->last;
  996. YACME_update( cmpnt, upoint->last );
  997. freePoint( upoint );
  998. }
  999. /*---------------------------------------------------------------------------*
  1000.  * MovePoint
  1001.  *---------------------------------------------------------------------------*/
  1002. int
  1003. MovePoint( int mousex, int mousey )
  1004. {
  1005. float x, y, dx, dy, minx, maxx;
  1006. OrthoTransform( mousex, mousey, &x, &y );
  1007. y = SUP( INF(y,(float)MAXNDX), 0. );
  1008. x = ((x-(int)x)<.5) ? (float)(int)x : (float)(int)(x+1);
  1009. y = ((y-(int)y)<.5) ? (float)(int)y : (float)(int)(y+1);
  1010. if ( curPoint->next != NULL && curPoint->last!= NULL )
  1011. {
  1012. minx = curPoint->last->x + 1.;
  1013. maxx = curPoint->next->x - 1.;
  1014. x = SUP( INF(x, maxx), minx );
  1015. dx = (float)x - curPoint->x;
  1016. curPoint->x = (float) x;
  1017. curPoint->tg.x0 += (float) dx;
  1018. curPoint->tg.x1 += (float) dx;
  1019. }
  1020. dy = (float)y - curPoint->y;
  1021. curPoint->y = (float)y;
  1022. curPoint->tg.y0 += (float) dy;
  1023. curPoint->tg.y1 += (float) dy;
  1024. return 1;
  1025. }
  1026. /*---------------------------------------------------------------------------*
  1027.  * MoveTangente
  1028.  *---------------------------------------------------------------------------*/
  1029. int
  1030. MoveTangente( int sens, int mousex, int mousey )
  1031. {
  1032. float x, y, dx, dy, slope;
  1033. Tangente *tg;
  1034. OrthoTransform( mousex, mousey, &x, &y );
  1035. if ( sens == -1 )
  1036. {
  1037. x = INF(x, curPoint->x);
  1038. }
  1039. else
  1040. {
  1041. x = SUP(x, curPoint->x);
  1042. }
  1043. if ( x != curPoint->x )
  1044. {
  1045. slope = (curPoint->y - y);
  1046. slope /= (curPoint->x - x);
  1047. dx = 25. / fsqrt( slope*slope + 1. );
  1048. dy = dx*slope;
  1049. }
  1050. else
  1051. {
  1052. dx = 0.;
  1053. dy = (curPoint->y < y) ? sens*25. : -sens*25.;
  1054. }
  1055. dx *= LUTRATIO;
  1056. dy *= LUTRATIO;
  1057. tg = &curPoint->tg;
  1058. tg->x0 = curPoint->x;
  1059. tg->y0 = curPoint->y;
  1060. if ( curPoint->last != NULL ) {
  1061. tg->x0 -= dx;
  1062. tg->y0 -= dy;
  1063. }
  1064. tg->x1 = curPoint->x;
  1065. tg->y1 = curPoint->y;
  1066. if ( curPoint->next != NULL )
  1067. {
  1068. tg->x1 += dx;
  1069. tg->y1 += dy;
  1070. }
  1071. return 1;
  1072. }
  1073. /*---------------------------------------------------------------------------*
  1074.  * GetPolynome
  1075.  *---------------------------------------------------------------------------*/
  1076. /*
  1077. we want a polynom P(x) = Ax^3 + Bx^2 + Cx + D
  1078. so that : P(a0) = b0, P'(a0) = t0, P(a1) = b1, P'(a1) = t1 
  1079. i.e.
  1080. | a0^3 a0^2 a0 1 | |A|   |b0|
  1081. | a1^3 a1^2 a1 1 | |B| = |b1|
  1082. | 3a0^2 2a0 1 0 | |C|   |t0|
  1083. | 3a1^2 2a1 1 0 | |D|   |t1|
  1084. */
  1085. void
  1086. GetPolynome(
  1087. int mode,
  1088. float a0, float b0, float t0,
  1089. float a1, float b1, float t1,
  1090. float coeff[4] )
  1091. {
  1092. Matrix mat, INV_mat;
  1093. int i;
  1094. float val;
  1095. switch (mode)
  1096. {
  1097. case CONSTANT:
  1098. /* we want P(x) = b0 */
  1099. coeff[0] = 0.;
  1100. coeff[1] = 0.;
  1101. coeff[2] = 0.;
  1102. coeff[3] = b0;
  1103. break;
  1104. case LINEAR:
  1105. /*
  1106. we want P(x) = b0 + (x-a0)/(a1-a0)*(b1-b0)
  1107. i.e. P(x) = x*[(b1-b0)/(a1-a0)] + b0 - a0*[(b1-b0)/(a1-a0)]
  1108. */
  1109. val = (b1-b0)/(a1-a0);
  1110. coeff[0] = 0.;
  1111. coeff[1] = 0.;
  1112. coeff[2] = val;
  1113. coeff[3] = b0 - a0*val;
  1114. break;
  1115. case POLYNOMIAL:
  1116. /*
  1117. we want a polynom P(x) = Ax^3 + Bx^2 + Cx + D
  1118. so that : P(a0) = b0, P'(a0) = t0, P(a1) = b1, P'(a1) = t1 
  1119. i.e.
  1120. | a0^3 a0^2 a0 1 | |A|   |b0|
  1121. | a1^3 a1^2 a1 1 | |B| = |b1|
  1122. | 3a0^2 2a0 1 0 | |C|   |t0|
  1123. | 3a1^2 2a1 1 0 | |D|   |t1|
  1124. */
  1125. val = 1.;
  1126. for (i=3; i>=0; i--)
  1127. {
  1128. mat[0][i] = val;
  1129. val *= a0;
  1130. }
  1131. val = 1.;
  1132. for (i=3; i>=0; i--)
  1133. {
  1134. mat[1][i] = val;
  1135. val *= a1;
  1136. }
  1137. mat[2][3] = 0.;
  1138. mat[2][2] = 1.;
  1139. mat[2][1] = 2.*a0;
  1140. mat[2][0] = 3.*a0*a0;
  1141. mat[3][3] = 0.;
  1142. mat[3][2] = 1.;
  1143. mat[3][1] = 2.*a1;
  1144. mat[3][0] = 3.*a1*a1;
  1145. invertmat( mat, INV_mat );
  1146. for (i=0; i<4; i++)
  1147. coeff[i] = INV_mat[i][0]*b0 +
  1148. INV_mat[i][1]*b1 +
  1149. INV_mat[i][2]*t0 +
  1150. INV_mat[i][3]*t1;
  1151. break;
  1152. }
  1153. }
  1154. /*---------------------------------------------------------------------------*
  1155.  * OrthoTransform
  1156.  *---------------------------------------------------------------------------*/
  1157. void
  1158. OrthoTransform( int mx, int my, float *x, float *y )
  1159. {
  1160.  float xf, yf;
  1161.  xf = (float) mx;
  1162.  xf /= (float) W;
  1163.  xf *= (float) (RIGHT - LEFT);
  1164.  xf += (float) LEFT;
  1165.  yf = (float) my;
  1166.  yf /= (float) H;
  1167.  yf *= (float) (TOP - BOTTOM);
  1168.  yf += (float) BOTTOM;
  1169.  *x = xf;
  1170.  *y = yf;
  1171. }
  1172. /*---------------------------------------------------------------------------*
  1173.  * Polynome4
  1174.  *---------------------------------------------------------------------------*/
  1175. float
  1176. Polynome4( float x, float *coeff )
  1177. {
  1178.  int j;
  1179.  float val = coeff[0];
  1180.  for (j=1; j<4; j++) {
  1181. val *= x;
  1182. val += coeff[j];
  1183.  }
  1184.  return val;
  1185. }
  1186. /*---------------------------------------------------------------------------*
  1187.  * MAIN
  1188.  *---------------------------------------------------------------------------*/
  1189. #ifdef YACME_DBG
  1190. #include "RGBA.h"
  1191. int
  1192. main( int argc, char *argv[] )
  1193. {
  1194. glutInit( &argc, argv );
  1195. YACME_init(
  1196. 0, 0, WINWIDTH, WINHEIGHT,
  1197. 256, (float**)RGBA,
  1198. NULL, NULL
  1199. );
  1200. glutMainLoop();
  1201. return 0;             /* ANSI C requires main to return int. */
  1202. }
  1203. #endif