home *** CD-ROM | disk | FTP | other *** search
/ AI Game Programming Wisdom / AIGameProgrammingWisdom.iso / SourceCode / 02 Useful Techniques / 08 Zarozinski / src / ffllapi / MemberFuncTri.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-16  |  8.5 KB  |  390 lines

  1. //
  2. // File:    MemberFuncTri.cpp
  3. //
  4. // Purpose:    Implementation of the MemberFuncTri membership function
  5. //
  6. // Copyright ⌐ 1999-2001 Louder Than A Bomb! Software
  7. //
  8. // This file is part of the FFLL (Free Fuzzy Logic Library) project (http://ffll.sourceforge.net)
  9. // It is released under the BSD license, see http://ffll.sourceforge.net/license.txt for the full text.
  10. //
  11.  
  12. #include "MemberFuncTri.h"
  13. #include "MemberFuncSingle.h"
  14. #include "FuzzyModelBase.h"
  15. #include "FuzzyVariableBase.h"
  16.  
  17. #ifdef _DEBUG  
  18. #undef THIS_FILE
  19. static char THIS_FILE[]=__FILE__; 
  20. #endif
  21.  
  22. //
  23. // Function:    MemberFuncTri()
  24. // 
  25. // Purpose:        Constructor
  26. //
  27. // Arguments:
  28. //
  29. //        FuzzySetBase* _parent - Set this member function is part of
  30. //
  31. // Returns:
  32. //
  33. //        nothing
  34. //
  35. // Author:    Michael Zarozinski
  36. // Date:    8/99
  37. // 
  38. // Modification History
  39. // Author    Date        Modification
  40. // ------    ----        ------------
  41. //
  42. //
  43. MemberFuncTri::MemberFuncTri(FuzzySetBase* _parent) : MemberFuncBase(_parent), FFLLBase(_parent)
  44. {
  45.     // create the nodes array
  46.     alloc_nodes( get_node_count() );
  47.  
  48. } // MemberFuncTri::MemberFuncTri()
  49.  
  50. //
  51. // Function:    ~MemberFuncTri()
  52. // 
  53. // Purpose:        Destructor
  54. //
  55. // Arguments:
  56. //
  57. //        none
  58. //
  59. // Returns:
  60. //
  61. //        nothing
  62. //
  63. // Author:    Michael Zarozinski
  64. // Date:    8/99
  65. // 
  66. // Modification History
  67. // Author    Date        Modification
  68. // ------    ----        ------------
  69. //
  70. //
  71. MemberFuncTri::~MemberFuncTri() 
  72. {
  73.     // nothing to do, base class(es) handle everything
  74. }
  75.  
  76. //
  77. // Function: set_node()
  78. // 
  79. // Purpose:    This function moves a point to a new position. It performs
  80. //            checks to make sure the nodes are at valid positions (such as
  81. //            not allowing the last point to be BEFORE the mid point.
  82. // 
  83. // Arguments:
  84. //
  85. //        int            idx            -    index of the point to move
  86. //        int            x            -    x position to move to (in variable coords)
  87. //        int            y            -    x position to move to (in variable coords)
  88. //        bool        validate    -    indicates if we should perorm sanity checks (default is true)
  89. //
  90. // Returns:
  91. //
  92. //        void
  93. // 
  94. // Globals:
  95. //
  96. // Author:    Michael Zarozinski    
  97. // Date:    6/21/99
  98. // 
  99. //    Modification History
  100. //    Author        Date        Modification
  101. //    ------        ----        ------------
  102. //     
  103. //
  104.  
  105. void MemberFuncTri::set_node(int idx, int x, int y, bool validate /* = true */)
  106. {
  107.     if (!validate)
  108.         {
  109.         nodes[idx].y = y;
  110.         nodes[idx].x = x;
  111.         return;
  112.         }
  113.  
  114.      // set the 'y' value based on the shape of this curve - we don't
  115.     // allow them to change the 'y' for the triangle shape
  116.  
  117.     if (idx == 0 || idx == 2)
  118.         nodes[idx].y = 0;
  119.     else
  120.         nodes[idx].y = FuzzyVariableBase::get_dom_array_max_idx();
  121.  
  122.     // perform some sanity checks on the 'x' position
  123.  
  124.     if (idx == 0)
  125.         {
  126.         // we're dealing with an start point
  127.         if ( x > get_center_x())
  128.              nodes[idx].x = get_center_x();
  129.         else
  130.             nodes[idx].x = x; // overloaded operator=() performs some additional validation for us
  131.         }
  132.     else if (idx == 1)
  133.         {
  134.         // we're dealing with the mid point which can't go beyond the end points
  135.         if ( x < get_start_x())
  136.             nodes[idx].x = get_start_x();
  137.         else if ( x > get_end_x())
  138.             nodes[idx].x = get_end_x();
  139.         else
  140.             nodes[idx].x = x; // overloaded operator=() performs some additional validation for us
  141.         } 
  142.     else
  143.         { 
  144.         // we're dealing with the last point
  145.         if ( x < get_center_x())
  146.             nodes[idx].x = get_center_x();
  147.         else  
  148.             nodes[idx].x = x; // overloaded operator=() performs some additional validation for us
  149.         }
  150.  
  151. } // end MemberFuncTri::set_node()
  152.   
  153.  
  154. //
  155. // Function:    init_nodes()
  156. // 
  157. // Purpose:        Initialized all the nodes to reasonable values depending on the 
  158. //                mid-point and width passed in.
  159. //
  160. // Arguments:
  161. //
  162. //            int        mid_pt_x    -    mid point of the member func
  163. //            int        width        -    how wide this set is
  164. // 
  165. // Returns:
  166. //
  167. //            none
  168. //
  169. // Author:    Michael Zarozinski
  170. // Date:    6/21/99
  171. // 
  172. // Modification History
  173. // Author    Date        Modification
  174. // ------    ----        ------------
  175. //
  176. //
  177.  
  178. void MemberFuncTri::init_nodes(int mid_pt_x, int width)
  179. {
  180.      nodes[0].x = mid_pt_x - width/2;
  181.     nodes[0].y = 0;
  182.  
  183.     nodes[1].x = mid_pt_x;
  184.     nodes[1].y = FuzzyVariableBase::get_dom_array_max_idx();  
  185.  
  186.     nodes[2].x = nodes[1].x + width/2;
  187.     nodes[2].y = 0;
  188.  
  189.     calc(); // re-calc values array
  190.  
  191. } // end MemberFuncTri::init_nodes()
  192.  
  193. //
  194. // Function:    set_ramp()
  195. // 
  196. // Purpose:        Virtual function that sets the nodes appropriately
  197. //                depending on the type of ramp (or no ramp) that we want.
  198. //
  199. // Arguments:
  200. //
  201. //        int left_right_ind        -    indicates if we're making a left (1) or right (0) ramp
  202. //        int hi_lo_ind            -    indicates if we're creating (1) or removing (0) ramp
  203. //
  204. // Returns:
  205. //
  206. //        void
  207. //
  208. // Author:    Michael Zarozinski
  209. // Date:    9/99
  210. // 
  211. // Modification History
  212. // Author    Date        Modification
  213. // ------    ----        ------------
  214. //
  215. //
  216. void  MemberFuncTri::set_ramp(int hi_lo_ind, int left_right_ind)
  217. {
  218.  
  219.     // if we're removing a ramp, move the middle node
  220.      if (hi_lo_ind == 0)
  221.         {
  222.         // move only the middle term
  223.         nodes[1].x = nodes[0].x + (nodes[2].x - nodes[0].x)/2;
  224.         }
  225.     else
  226.         {
  227.         // we're creating a ramp...
  228.          if (left_right_ind)
  229.             {
  230.             // make the left the ramp
  231.             nodes[0].x = nodes[1].x = 0;
  232.             }
  233.         else
  234.             {
  235.             // make the right the ramp
  236.             nodes[2].x = nodes[1].x = FuzzyVariableBase::get_x_array_max_idx();
  237.             }
  238.         } // end if making hi ramp
  239.  
  240.     // call the ancestor to deal with common code...
  241.     MemberFuncBase::set_ramp(hi_lo_ind, left_right_ind);
  242.  
  243. } // end MemberFuncTri::set_ramp()
  244.  
  245. //
  246. // Function:    calc()
  247. // 
  248. // Purpose:        Virtual function that calculates the 'y' points for this curve
  249. //                 and fills in the values[] array.
  250. //
  251. // Arguments:
  252. //
  253. //        none
  254. //
  255. // Returns:
  256. //
  257. //        void
  258. //
  259. // Author:    Michael Zarozinski
  260. // Date:    5/99
  261. // 
  262. // Modification History
  263. // Author    Date        Modification
  264. // ------    ----        ------------
  265. //
  266. //  
  267. void MemberFuncTri::calc()
  268. {
  269.     int        i;    // counter
  270.     double    m;    // slope of the curve, this is the 'm' in y = mx + b
  271.      double    b;    // b for y = mx + b
  272.  
  273.     // clear out the whole values[] array
  274.     clear_values( );
  275.  
  276.     // calc the slope for the first part of the line...
  277.  
  278.     double divisor = nodes[1].x - nodes[0].x;
  279.  
  280.     m = 1.0;
  281.  
  282.     // make sure we don't div by 0...  
  283.     if (divisor )
  284.          m /= divisor; // this is 1/divisor cuz the 'y' max is 1.0
  285.  
  286.     // fill in the 'y' values for the first part of this member func
  287.  
  288.     for (i = nodes[0].x; i <= nodes[1].x; i++)
  289.         {
  290.         // we "shift" things by subtracting nodes[0].x so the calc of the y = mx + b
  291.         set_value(i, m * (i - nodes[0].x) ); // y = mx + b (b is zero in this case)
  292.         }
  293.  
  294.     // calc the slope for the 2nd part of the line...
  295.  
  296.     divisor = nodes[2].x - nodes[1].x;
  297.  
  298.     m = -1.0;    // slope is negative for this part of the curve
  299.  
  300.     if (divisor)
  301.          m /=  divisor;
  302.        
  303.     b = 1.0;
  304.  
  305.     // fill in the 'y' values for the 2nd part of the curve
  306.      for (i = nodes[1].x; i <= nodes[2].x; i++)
  307.         {
  308.         // we "shift" things by subtracting nodes[1].x so the calc of the y = mx + b
  309.         set_value(i, (m * (i - nodes[1].x)) + b );  
  310.         }
  311.  
  312. } // end MemberFuncTri::calc()
  313.  
  314. //
  315. // Function:    expand()
  316. // 
  317. // Purpose:        Uniformly expands this member func around it's center
  318. //
  319. // Arguments:
  320. //
  321. //        int x_delta - how much to expand the member func by        
  322. //
  323. // Returns:
  324. //
  325. //        void
  326. //
  327. // Author:    Michael Zarozinski
  328. // Date:    9/99
  329. // 
  330. // Modification History
  331. // Author    Date        Modification
  332. // ------    ----        ------------
  333. //
  334. //
  335. void MemberFuncTri::expand(int x_delta )
  336. {
  337.     int delta = abs(x_delta);
  338.  
  339.     move_node(0, nodes[0].x - delta, nodes[0].y);
  340.     move_node(2, nodes[2].x + delta, nodes[2].y);
  341.  
  342. } // end MemberFuncTri::expand()
  343.  
  344. //
  345. // Function:    shrink()
  346. // 
  347. // Purpose:        Uniformly shrinks this member func around it's center
  348. //
  349. // Arguments:
  350. //
  351. //        int x_delta - how much to shrink the member func by        
  352. //
  353. // Returns:
  354. //
  355. //        void
  356. //
  357. // Author:    Michael Zarozinski
  358. // Date:    9/99
  359. // 
  360. // Modification History
  361. // Author    Date        Modification
  362. // ------    ----        ------------
  363. //
  364. //
  365. void MemberFuncTri::shrink(int x_delta )
  366. {
  367.     int delta = abs(x_delta);
  368.  
  369.     move_node(0, nodes[0].x + delta, nodes[0].y);
  370.     move_node(2, nodes[2].x - delta, nodes[2].y);
  371.  
  372. } // end MemberFuncTri::shrink()
  373.  
  374. /////////////////////////////////////////////////////////////////////
  375. ////////// Trivial Functions That Don't Require Headers /////////////
  376. /////////////////////////////////////////////////////////////////////
  377.  
  378. int MemberFuncTri::get_center_x(void) const 
  379. {
  380.     return nodes[1].x;
  381. };
  382. int MemberFuncTri::get_func_type() const 
  383. {
  384.     return MemberFuncBase::TRIANGLE;
  385. };
  386. int MemberFuncTri::get_node_count() const 
  387.     return 3;
  388. };
  389.