dcNumericRange.I 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. // Filename: dcNumericRange.I
  2. // Created by: drose (21Jun04)
  3. //
  4. ////////////////////////////////////////////////////////////////////
  5. //
  6. // PANDA 3D SOFTWARE
  7. // Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
  8. //
  9. // All use of this software is subject to the terms of the Panda 3d
  10. // Software license. You should have received a copy of this license
  11. // along with this source code; you will also find a current copy of
  12. // the license at http://etc.cmu.edu/panda3d/docs/license/ .
  13. //
  14. // To contact the maintainers of this program write to
  15. // [email protected] .
  16. //
  17. ////////////////////////////////////////////////////////////////////
  18. ////////////////////////////////////////////////////////////////////
  19. // Function: DCNumericRange::Constructor
  20. // Access: Public
  21. // Description:
  22. ////////////////////////////////////////////////////////////////////
  23. template <class NUM>
  24. INLINE DCNumericRange<NUM>::
  25. DCNumericRange() {
  26. }
  27. ////////////////////////////////////////////////////////////////////
  28. // Function: DCNumericRange::Constructor
  29. // Access: Public
  30. // Description:
  31. ////////////////////////////////////////////////////////////////////
  32. template <class NUM>
  33. INLINE DCNumericRange<NUM>::
  34. DCNumericRange(Number min, Number max) {
  35. add_range(min, max);
  36. }
  37. ////////////////////////////////////////////////////////////////////
  38. // Function: DCNumericRange::Copy Constructor
  39. // Access: Public
  40. // Description:
  41. ////////////////////////////////////////////////////////////////////
  42. template <class NUM>
  43. INLINE DCNumericRange<NUM>::
  44. DCNumericRange(const DCNumericRange<NUM> &copy) :
  45. _ranges(copy._ranges)
  46. {
  47. }
  48. ////////////////////////////////////////////////////////////////////
  49. // Function: DCNumericRange::Copy Assignment Operator
  50. // Access: Public
  51. // Description:
  52. ////////////////////////////////////////////////////////////////////
  53. template <class NUM>
  54. INLINE void DCNumericRange<NUM>::
  55. operator = (const DCNumericRange<NUM> &copy) {
  56. _ranges = copy._ranges;
  57. }
  58. ////////////////////////////////////////////////////////////////////
  59. // Function: DCNumericRange::is_in_range
  60. // Access: Public
  61. // Description: Returns true if the indicated number is within the
  62. // specified range, false otherwise.
  63. ////////////////////////////////////////////////////////////////////
  64. template <class NUM>
  65. bool DCNumericRange<NUM>::
  66. is_in_range(Number num) const {
  67. if (_ranges.empty()) {
  68. return true;
  69. }
  70. TYPENAME Ranges::const_iterator ri;
  71. for (ri = _ranges.begin(); ri != _ranges.end(); ++ri) {
  72. if (num >= (*ri)._min && num <= (*ri)._max) {
  73. return true;
  74. }
  75. }
  76. return false;
  77. }
  78. ////////////////////////////////////////////////////////////////////
  79. // Function: DCNumericRange::validate
  80. // Access: Public
  81. // Description: Convenience function to validate the indicated
  82. // number. If the number is within the specified range,
  83. // does nothing; otherwise, if it is outside the range,
  84. // sets range_error to true.
  85. ////////////////////////////////////////////////////////////////////
  86. template <class NUM>
  87. INLINE void DCNumericRange<NUM>::
  88. validate(Number num, bool &range_error) const {
  89. if (!is_in_range(num)) {
  90. range_error = true;
  91. }
  92. }
  93. ////////////////////////////////////////////////////////////////////
  94. // Function: DCNumericRange::has_one_value
  95. // Access: Public
  96. // Description: Returns true if the numeric range specifies exactly
  97. // one legal value, false if multiple values are legal.
  98. ////////////////////////////////////////////////////////////////////
  99. template <class NUM>
  100. INLINE bool DCNumericRange<NUM>::
  101. has_one_value() const {
  102. return _ranges.size() == 1 && _ranges[0]._min == _ranges[0]._max;
  103. }
  104. ////////////////////////////////////////////////////////////////////
  105. // Function: DCNumericRange::get_one_value
  106. // Access: Public
  107. // Description: If has_one_value() returns true, this returns the one
  108. // legal value accepted by the numeric range.
  109. ////////////////////////////////////////////////////////////////////
  110. template <class NUM>
  111. INLINE TYPENAME DCNumericRange<NUM>::Number DCNumericRange<NUM>::
  112. get_one_value() const {
  113. nassertr(has_one_value(), 0);
  114. return _ranges[0]._min;
  115. }
  116. ////////////////////////////////////////////////////////////////////
  117. // Function: DCNumericRange::generate_hash
  118. // Access: Public
  119. // Description:
  120. ////////////////////////////////////////////////////////////////////
  121. template <class NUM>
  122. void DCNumericRange<NUM>::
  123. generate_hash(HashGenerator &hashgen) const {
  124. if (!_ranges.empty()) {
  125. hashgen.add_int(_ranges.size());
  126. TYPENAME Ranges::const_iterator ri;
  127. for (ri = _ranges.begin(); ri != _ranges.end(); ++ri) {
  128. // We don't account for the fractional part of floating-point
  129. // ranges here. Shouldn't be a real issue.
  130. hashgen.add_int((int)(*ri)._min);
  131. hashgen.add_int((int)(*ri)._max);
  132. }
  133. }
  134. }
  135. ////////////////////////////////////////////////////////////////////
  136. // Function: DCNumericRange::output
  137. // Access: Public
  138. // Description:
  139. ////////////////////////////////////////////////////////////////////
  140. template <class NUM>
  141. void DCNumericRange<NUM>::
  142. output(ostream &out, Number divisor) const {
  143. if (!_ranges.empty()) {
  144. TYPENAME Ranges::const_iterator ri;
  145. ri = _ranges.begin();
  146. output_minmax(out, divisor, *ri);
  147. ++ri;
  148. while (ri != _ranges.end()) {
  149. out << ", ";
  150. output_minmax(out, divisor, *ri);
  151. ++ri;
  152. }
  153. }
  154. }
  155. ////////////////////////////////////////////////////////////////////
  156. // Function: DCNumericRange::output_char
  157. // Access: Public
  158. // Description: Outputs the range, formatting the numeric values as
  159. // quoted ASCII characters.
  160. ////////////////////////////////////////////////////////////////////
  161. template <class NUM>
  162. void DCNumericRange<NUM>::
  163. output_char(ostream &out, Number divisor) const {
  164. if (divisor != 1) {
  165. output(out, divisor);
  166. } else {
  167. if (!_ranges.empty()) {
  168. TYPENAME Ranges::const_iterator ri;
  169. ri = _ranges.begin();
  170. output_minmax_char(out, *ri);
  171. ++ri;
  172. while (ri != _ranges.end()) {
  173. out << ", ";
  174. output_minmax_char(out, *ri);
  175. ++ri;
  176. }
  177. }
  178. }
  179. }
  180. ////////////////////////////////////////////////////////////////////
  181. // Function: DCNumericRange::clear
  182. // Access: Public
  183. // Description:
  184. ////////////////////////////////////////////////////////////////////
  185. template <class NUM>
  186. INLINE void DCNumericRange<NUM>::
  187. clear() {
  188. _ranges.clear();
  189. }
  190. ////////////////////////////////////////////////////////////////////
  191. // Function: DCNumericRange::add_range
  192. // Access: Public
  193. // Description: Adds a new minmax to the list of ranges. This is
  194. // normally called only during dc file parsing. Returns
  195. // true if successful, or false if the new minmax
  196. // overlaps an existing minmax.
  197. ////////////////////////////////////////////////////////////////////
  198. template <class NUM>
  199. bool DCNumericRange<NUM>::
  200. add_range(Number min, Number max) {
  201. // Check for an overlap. This is probably indicative of a typo and
  202. // should be reported.
  203. if (max < min) {
  204. return false;
  205. }
  206. TYPENAME Ranges::const_iterator ri;
  207. for (ri = _ranges.begin(); ri != _ranges.end(); ++ri) {
  208. if ((min >= (*ri)._min && min <= (*ri)._max) ||
  209. (max >= (*ri)._min && max <= (*ri)._max) ||
  210. (min < (*ri)._min && max > (*ri)._max)) {
  211. return false;
  212. }
  213. }
  214. MinMax minmax;
  215. minmax._min = min;
  216. minmax._max = max;
  217. _ranges.push_back(minmax);
  218. return true;
  219. }
  220. ////////////////////////////////////////////////////////////////////
  221. // Function: DCNumericRange::is_empty
  222. // Access: Private
  223. // Description: Returns true if the range contains no elements (and
  224. // thus allows all numbers), false if it contains at
  225. // least one.
  226. ////////////////////////////////////////////////////////////////////
  227. template <class NUM>
  228. INLINE bool DCNumericRange<NUM>::
  229. is_empty() const {
  230. return _ranges.empty();
  231. }
  232. ////////////////////////////////////////////////////////////////////
  233. // Function: DCNumericRange::get_num_ranges
  234. // Access: Private
  235. // Description: Returns the number of minmax components in the range
  236. // description.
  237. ////////////////////////////////////////////////////////////////////
  238. template <class NUM>
  239. INLINE int DCNumericRange<NUM>::
  240. get_num_ranges() const {
  241. return _ranges.size();
  242. }
  243. ////////////////////////////////////////////////////////////////////
  244. // Function: DCNumericRange::get_min
  245. // Access: Private
  246. // Description: Returns the minimum value defined by the nth component.
  247. ////////////////////////////////////////////////////////////////////
  248. template <class NUM>
  249. INLINE TYPENAME DCNumericRange<NUM>::Number DCNumericRange<NUM>::
  250. get_min(int n) const {
  251. nassertr(n >= 0 && n < (int)_ranges.size(), 0);
  252. return _ranges[n]._min;
  253. }
  254. ////////////////////////////////////////////////////////////////////
  255. // Function: DCNumericRange::get_max
  256. // Access: Private
  257. // Description: Returns the maximum value defined by the nth component.
  258. ////////////////////////////////////////////////////////////////////
  259. template <class NUM>
  260. INLINE TYPENAME DCNumericRange<NUM>::Number DCNumericRange<NUM>::
  261. get_max(int n) const {
  262. nassertr(n >= 0 && n < (int)_ranges.size(), 0);
  263. return _ranges[n]._max;
  264. }
  265. ////////////////////////////////////////////////////////////////////
  266. // Function: DCNumericRange::output_minmax
  267. // Access: Private
  268. // Description: Outputs a single element of the range description.
  269. ////////////////////////////////////////////////////////////////////
  270. template <class NUM>
  271. INLINE void DCNumericRange<NUM>::
  272. output_minmax(ostream &out, Number divisor, const MinMax &range) const {
  273. if (divisor == 1) {
  274. if (range._min == range._max) {
  275. out << range._min;
  276. } else {
  277. out << range._min << "-" << range._max;
  278. }
  279. } else {
  280. if (range._min == range._max) {
  281. out << (double)range._min / (double)divisor;
  282. } else {
  283. out << (double)range._min / (double)divisor
  284. << "-"
  285. << (double)range._max / (double)divisor;
  286. }
  287. }
  288. }
  289. ////////////////////////////////////////////////////////////////////
  290. // Function: DCNumericRange::output_minmax_char
  291. // Access: Private
  292. // Description: Outputs a single element of the range description.
  293. ////////////////////////////////////////////////////////////////////
  294. template <class NUM>
  295. INLINE void DCNumericRange<NUM>::
  296. output_minmax_char(ostream &out, const MinMax &range) const {
  297. if (range._min == range._max) {
  298. DCPacker::enquote_string(out, '\'', string(1, range._min));
  299. } else {
  300. DCPacker::enquote_string(out, '\'', string(1, range._min));
  301. out << "-";
  302. DCPacker::enquote_string(out, '\'', string(1, range._max));
  303. }
  304. }