Panda3D
|
00001 // Filename: dcNumericRange.I 00002 // Created by: drose (21Jun04) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 00016 //////////////////////////////////////////////////////////////////// 00017 // Function: DCNumericRange::Constructor 00018 // Access: Public 00019 // Description: 00020 //////////////////////////////////////////////////////////////////// 00021 template <class NUM> 00022 INLINE DCNumericRange<NUM>:: 00023 DCNumericRange() { 00024 } 00025 00026 //////////////////////////////////////////////////////////////////// 00027 // Function: DCNumericRange::Constructor 00028 // Access: Public 00029 // Description: 00030 //////////////////////////////////////////////////////////////////// 00031 template <class NUM> 00032 INLINE DCNumericRange<NUM>:: 00033 DCNumericRange(Number min, Number max) { 00034 add_range(min, max); 00035 } 00036 00037 //////////////////////////////////////////////////////////////////// 00038 // Function: DCNumericRange::Copy Constructor 00039 // Access: Public 00040 // Description: 00041 //////////////////////////////////////////////////////////////////// 00042 template <class NUM> 00043 INLINE DCNumericRange<NUM>:: 00044 DCNumericRange(const DCNumericRange<NUM> ©) : 00045 _ranges(copy._ranges) 00046 { 00047 } 00048 00049 //////////////////////////////////////////////////////////////////// 00050 // Function: DCNumericRange::Copy Assignment Operator 00051 // Access: Public 00052 // Description: 00053 //////////////////////////////////////////////////////////////////// 00054 template <class NUM> 00055 INLINE void DCNumericRange<NUM>:: 00056 operator = (const DCNumericRange<NUM> ©) { 00057 _ranges = copy._ranges; 00058 } 00059 00060 //////////////////////////////////////////////////////////////////// 00061 // Function: DCNumericRange::is_in_range 00062 // Access: Public 00063 // Description: Returns true if the indicated number is within the 00064 // specified range, false otherwise. 00065 //////////////////////////////////////////////////////////////////// 00066 template <class NUM> 00067 bool DCNumericRange<NUM>:: 00068 is_in_range(Number num) const { 00069 if (_ranges.empty()) { 00070 return true; 00071 } 00072 00073 TYPENAME Ranges::const_iterator ri; 00074 for (ri = _ranges.begin(); ri != _ranges.end(); ++ri) { 00075 if (num >= (*ri)._min && num <= (*ri)._max) { 00076 return true; 00077 } 00078 } 00079 00080 return false; 00081 } 00082 00083 //////////////////////////////////////////////////////////////////// 00084 // Function: DCNumericRange::validate 00085 // Access: Public 00086 // Description: Convenience function to validate the indicated 00087 // number. If the number is within the specified range, 00088 // does nothing; otherwise, if it is outside the range, 00089 // sets range_error to true. 00090 //////////////////////////////////////////////////////////////////// 00091 template <class NUM> 00092 INLINE void DCNumericRange<NUM>:: 00093 validate(Number num, bool &range_error) const { 00094 if (!is_in_range(num)) { 00095 range_error = true; 00096 } 00097 } 00098 00099 //////////////////////////////////////////////////////////////////// 00100 // Function: DCNumericRange::has_one_value 00101 // Access: Public 00102 // Description: Returns true if the numeric range specifies exactly 00103 // one legal value, false if multiple values are legal. 00104 //////////////////////////////////////////////////////////////////// 00105 template <class NUM> 00106 INLINE bool DCNumericRange<NUM>:: 00107 has_one_value() const { 00108 return _ranges.size() == 1 && _ranges[0]._min == _ranges[0]._max; 00109 } 00110 00111 //////////////////////////////////////////////////////////////////// 00112 // Function: DCNumericRange::get_one_value 00113 // Access: Public 00114 // Description: If has_one_value() returns true, this returns the one 00115 // legal value accepted by the numeric range. 00116 //////////////////////////////////////////////////////////////////// 00117 template <class NUM> 00118 INLINE TYPENAME DCNumericRange<NUM>::Number DCNumericRange<NUM>:: 00119 get_one_value() const { 00120 nassertr(has_one_value(), 0); 00121 return _ranges[0]._min; 00122 } 00123 00124 //////////////////////////////////////////////////////////////////// 00125 // Function: DCNumericRange::generate_hash 00126 // Access: Public 00127 // Description: 00128 //////////////////////////////////////////////////////////////////// 00129 template <class NUM> 00130 void DCNumericRange<NUM>:: 00131 generate_hash(HashGenerator &hashgen) const { 00132 if (!_ranges.empty()) { 00133 hashgen.add_int(_ranges.size()); 00134 TYPENAME Ranges::const_iterator ri; 00135 for (ri = _ranges.begin(); ri != _ranges.end(); ++ri) { 00136 // We don't account for the fractional part of floating-point 00137 // ranges here. Shouldn't be a real issue. 00138 hashgen.add_int((int)(*ri)._min); 00139 hashgen.add_int((int)(*ri)._max); 00140 } 00141 } 00142 } 00143 00144 //////////////////////////////////////////////////////////////////// 00145 // Function: DCNumericRange::output 00146 // Access: Public 00147 // Description: 00148 //////////////////////////////////////////////////////////////////// 00149 template <class NUM> 00150 void DCNumericRange<NUM>:: 00151 output(ostream &out, Number divisor) const { 00152 if (!_ranges.empty()) { 00153 TYPENAME Ranges::const_iterator ri; 00154 ri = _ranges.begin(); 00155 output_minmax(out, divisor, *ri); 00156 ++ri; 00157 while (ri != _ranges.end()) { 00158 out << ", "; 00159 output_minmax(out, divisor, *ri); 00160 ++ri; 00161 } 00162 } 00163 } 00164 00165 //////////////////////////////////////////////////////////////////// 00166 // Function: DCNumericRange::output_char 00167 // Access: Public 00168 // Description: Outputs the range, formatting the numeric values as 00169 // quoted ASCII characters. 00170 //////////////////////////////////////////////////////////////////// 00171 template <class NUM> 00172 void DCNumericRange<NUM>:: 00173 output_char(ostream &out, Number divisor) const { 00174 if (divisor != 1) { 00175 output(out, divisor); 00176 00177 } else { 00178 if (!_ranges.empty()) { 00179 TYPENAME Ranges::const_iterator ri; 00180 ri = _ranges.begin(); 00181 output_minmax_char(out, *ri); 00182 ++ri; 00183 while (ri != _ranges.end()) { 00184 out << ", "; 00185 output_minmax_char(out, *ri); 00186 ++ri; 00187 } 00188 } 00189 } 00190 } 00191 00192 //////////////////////////////////////////////////////////////////// 00193 // Function: DCNumericRange::clear 00194 // Access: Public 00195 // Description: 00196 //////////////////////////////////////////////////////////////////// 00197 template <class NUM> 00198 INLINE void DCNumericRange<NUM>:: 00199 clear() { 00200 _ranges.clear(); 00201 } 00202 00203 //////////////////////////////////////////////////////////////////// 00204 // Function: DCNumericRange::add_range 00205 // Access: Public 00206 // Description: Adds a new minmax to the list of ranges. This is 00207 // normally called only during dc file parsing. Returns 00208 // true if successful, or false if the new minmax 00209 // overlaps an existing minmax. 00210 //////////////////////////////////////////////////////////////////// 00211 template <class NUM> 00212 bool DCNumericRange<NUM>:: 00213 add_range(Number min, Number max) { 00214 // Check for an overlap. This is probably indicative of a typo and 00215 // should be reported. 00216 if (max < min) { 00217 return false; 00218 } 00219 00220 TYPENAME Ranges::const_iterator ri; 00221 for (ri = _ranges.begin(); ri != _ranges.end(); ++ri) { 00222 if ((min >= (*ri)._min && min <= (*ri)._max) || 00223 (max >= (*ri)._min && max <= (*ri)._max) || 00224 (min < (*ri)._min && max > (*ri)._max)) { 00225 return false; 00226 } 00227 } 00228 00229 MinMax minmax; 00230 minmax._min = min; 00231 minmax._max = max; 00232 _ranges.push_back(minmax); 00233 00234 return true; 00235 } 00236 00237 //////////////////////////////////////////////////////////////////// 00238 // Function: DCNumericRange::is_empty 00239 // Access: Private 00240 // Description: Returns true if the range contains no elements (and 00241 // thus allows all numbers), false if it contains at 00242 // least one. 00243 //////////////////////////////////////////////////////////////////// 00244 template <class NUM> 00245 INLINE bool DCNumericRange<NUM>:: 00246 is_empty() const { 00247 return _ranges.empty(); 00248 } 00249 00250 //////////////////////////////////////////////////////////////////// 00251 // Function: DCNumericRange::get_num_ranges 00252 // Access: Private 00253 // Description: Returns the number of minmax components in the range 00254 // description. 00255 //////////////////////////////////////////////////////////////////// 00256 template <class NUM> 00257 INLINE int DCNumericRange<NUM>:: 00258 get_num_ranges() const { 00259 return _ranges.size(); 00260 } 00261 00262 //////////////////////////////////////////////////////////////////// 00263 // Function: DCNumericRange::get_min 00264 // Access: Private 00265 // Description: Returns the minimum value defined by the nth component. 00266 //////////////////////////////////////////////////////////////////// 00267 template <class NUM> 00268 INLINE TYPENAME DCNumericRange<NUM>::Number DCNumericRange<NUM>:: 00269 get_min(int n) const { 00270 nassertr(n >= 0 && n < (int)_ranges.size(), 0); 00271 return _ranges[n]._min; 00272 } 00273 00274 //////////////////////////////////////////////////////////////////// 00275 // Function: DCNumericRange::get_max 00276 // Access: Private 00277 // Description: Returns the maximum value defined by the nth component. 00278 //////////////////////////////////////////////////////////////////// 00279 template <class NUM> 00280 INLINE TYPENAME DCNumericRange<NUM>::Number DCNumericRange<NUM>:: 00281 get_max(int n) const { 00282 nassertr(n >= 0 && n < (int)_ranges.size(), 0); 00283 return _ranges[n]._max; 00284 } 00285 00286 //////////////////////////////////////////////////////////////////// 00287 // Function: DCNumericRange::output_minmax 00288 // Access: Private 00289 // Description: Outputs a single element of the range description. 00290 //////////////////////////////////////////////////////////////////// 00291 template <class NUM> 00292 INLINE void DCNumericRange<NUM>:: 00293 output_minmax(ostream &out, Number divisor, const MinMax &range) const { 00294 if (divisor == 1) { 00295 if (range._min == range._max) { 00296 out << range._min; 00297 } else { 00298 out << range._min << "-" << range._max; 00299 } 00300 } else { 00301 if (range._min == range._max) { 00302 out << (double)range._min / (double)divisor; 00303 } else { 00304 out << (double)range._min / (double)divisor 00305 << "-" 00306 << (double)range._max / (double)divisor; 00307 } 00308 } 00309 } 00310 00311 //////////////////////////////////////////////////////////////////// 00312 // Function: DCNumericRange::output_minmax_char 00313 // Access: Private 00314 // Description: Outputs a single element of the range description. 00315 //////////////////////////////////////////////////////////////////// 00316 template <class NUM> 00317 INLINE void DCNumericRange<NUM>:: 00318 output_minmax_char(ostream &out, const MinMax &range) const { 00319 if (range._min == range._max) { 00320 DCPacker::enquote_string(out, '\'', string(1, range._min)); 00321 } else { 00322 DCPacker::enquote_string(out, '\'', string(1, range._min)); 00323 out << "-"; 00324 DCPacker::enquote_string(out, '\'', string(1, range._max)); 00325 } 00326 }