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