libLAS API Reference  1.8.1
bounds.hpp
Go to the documentation of this file.
1 /******************************************************************************
2  * $Id$
3  *
4  * Project: libLAS - http://liblas.org - A BSD library for LAS format data.
5  * Purpose: LAS bounds class
6  * Author: Howard Butler, hobu.inc@gmail.com
7  *
8  ******************************************************************************
9  * Copyright (c) 2010, Howard Butler
10  *
11  * All rights reserved.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following
15  * conditions are met:
16  *
17  * * Redistributions of source code must retain the above copyright
18  * notice, this list of conditions and the following disclaimer.
19  * * Redistributions in binary form must reproduce the above copyright
20  * notice, this list of conditions and the following disclaimer in
21  * the documentation and/or other materials provided
22  * with the distribution.
23  * * Neither the name of the Martin Isenburg or Iowa Department
24  * of Natural Resources nor the names of its contributors may be
25  * used to endorse or promote products derived from this software
26  * without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
31  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
32  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
33  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
34  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
35  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
36  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
37  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
38  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
39  * OF SUCH DAMAGE.
40  ****************************************************************************/
41 
42 #ifndef LIBLAS_LASBOUNDS_HPP_INCLUDED
43 #define LIBLAS_LASBOUNDS_HPP_INCLUDED
44 
45 #include <liblas/detail/fwd.hpp>
46 #include <liblas/point.hpp>
47 #include <liblas/transform.hpp>
48 #include <liblas/detail/private_utility.hpp>
49 #include <liblas/export.hpp>
50 
51 #include <boost/concept_check.hpp>
52 // std
53 #include <cmath>
54 #include <limits>
55 #include <string>
56 #include <sstream>
57 #include <vector>
58 
59 
60 namespace liblas {
61 
62 
63 template <typename T>
65 {
66 public:
69 
70  typedef T value_type;
71 
72  Range(T mmin=(std::numeric_limits<T>::max)(), T mmax=(std::numeric_limits<T>::min)())
73  : minimum(mmin), maximum(mmax) {}
74 
75 
76  Range(Range const& other)
77  : minimum(other.minimum)
78  , maximum(other.maximum)
79  {
80  }
81 
82  Range& operator=(Range<T> const& rhs)
83  {
84  if (&rhs != this)
85  {
86  minimum = rhs.minimum;
87  maximum = rhs.maximum;
88  }
89  return *this;
90  }
91 
92  bool operator==(Range<T> const& rhs) const
93  {
94  return equal(rhs);
95  }
96 
97  bool operator!=(Range const& rhs) const
98  {
99  return !(equal(rhs));
100  }
101 
102  bool equal(Range const& other) const
103  {
104 
105  if (!(detail::compare_distance(minimum, other.minimum))
106  || !(detail::compare_distance(maximum, other.maximum)))
107  {
108  return false;
109  }
110 
111  return true;
112  }
113 
114  bool overlaps(Range const& r) const
115  {
116  return minimum < r.maximum && maximum > r.minimum;
117  }
118 
119  bool contains(Range const& r) const
120  {
121  return minimum <= r.minimum && r.maximum <= maximum;
122  }
123 
124  bool contains(T v) const
125  {
126  return minimum <= v && v <= maximum;
127  }
128 
129  bool empty(void) const
130  {
131  return detail::compare_distance(minimum, (std::numeric_limits<T>::max)()) && detail::compare_distance(maximum, (std::numeric_limits<T>::min)());
132  }
133 
134  void shift(T v)
135  {
136  minimum += v;
137  maximum += v;
138  }
139 
140  void scale(T v)
141  {
142  minimum *= v;
143  maximum *= v;
144  }
145 
146  void clip(Range const& r)
147  {
148  if (r.minimum > minimum)
149  minimum = r.minimum;
150  if (r.maximum < maximum)
151  maximum = r.maximum;
152  }
153 
154  void grow(T v)
155  {
156  if (v < minimum)
157  minimum = v;
158  if (v > maximum)
159  maximum = v;
160  }
161 
162  void grow(Range const& r)
163  {
164  grow(r.minimum);
165  grow(r.maximum);
166  }
167 
168  T length() const
169  {
170  return maximum - minimum;
171  }
172 };
173 
174 template <typename T>
175 class Bounds
176 {
177 public:
178 
179  typedef T value_type;
180  typedef typename std::vector< Range<T> >::size_type size_type;
181 
182  typedef typename std::vector< Range<T> > RangeVec;
183 private:
184 
185  RangeVec ranges;
186 
187 public:
188 
190 {
191  ranges.resize(0);
192 }
193 
194 Bounds(Bounds const& other)
195  :
196  ranges(other.ranges)
197 {
198 }
199 
200 Bounds(RangeVec const& rngs)
201  :
202  ranges(rngs)
203 {
204 }
205 
206 Bounds( T minx,
207  T miny,
208  T minz,
209  T maxx,
210  T maxy,
211  T maxz)
212 {
213  ranges.resize(3);
214 
215  ranges[0].minimum = minx;
216  ranges[1].minimum = miny;
217  ranges[2].minimum = minz;
218 
219  ranges[0].maximum = maxx;
220  ranges[1].maximum = maxy;
221  ranges[2].maximum = maxz;
222 
223 #ifdef DEBUG
224  verify();
225 #endif
226 
227 }
228 
229 Bounds( T minx,
230  T miny,
231  T maxx,
232  T maxy)
233 {
234 
235  ranges.resize(2);
236 
237  ranges[0].minimum = minx;
238  ranges[1].minimum = miny;
239 
240  ranges[0].maximum = maxx;
241  ranges[1].maximum = maxy;
242 
243 #ifdef DEBUG
244  verify();
245 #endif
246 
247 }
248 
249 Bounds( const Point& min, const Point& max)
250 {
251  ranges.resize(3);
252 
253  ranges[0].minimum = min.GetX();
254  ranges[1].minimum = min.GetY();
255  ranges[2].minimum = min.GetZ();
256 
257  ranges[0].maximum = max.GetX();
258  ranges[1].maximum = max.GetY();
259  ranges[2].maximum = max.GetZ();
260 
261 #ifdef DEBUG
262  verify();
263 #endif
264 
265 }
266 
267 
268 // Bounds( Vector const& low, Vector const& high)
269 // {
270 // if (low.size() != high.size() ) {
271 // std::ostringstream msg;
272 // msg << "Bounds dimensions are not equal. Low bounds dimensions are " << low.size()
273 // << " and the high bounds are " << high.size();
274 // throw std::runtime_error(msg.str());
275 // }
276 // mins.resize(low.size());
277 //
278 // mins = low;
279 // maxs = high;
280 //
281 // #ifdef DEBUG
282 // verify();
283 // #endif
284 //
285 // }
286 
287 T (min)(std::size_t const& index) const
288 {
289  if (ranges.size() <= index) {
290  // std::ostringstream msg;
291  // msg << "Bounds dimensions, " << ranges.size() <<", is less "
292  // << "than the given index, " << index;
293  // throw std::runtime_error(msg.str());
294  return 0;
295  }
296  return ranges[index].minimum;
297 }
298 
299 void (min)(std::size_t const& index, T v)
300 {
301  if (ranges.size() <= index) {
302  ranges.resize(index + 1);
303  }
304  ranges[index].minimum = v;
305 }
306 
307 T (max)(std::size_t const& index) const
308 {
309  if (ranges.size() <= index) {
310  // std::ostringstream msg;
311  // msg << "Bounds dimensions, " << ranges.size() <<", is less "
312  // << "than the given index, " << index;
313  // throw std::runtime_error(msg.str());
314  return 0;
315  }
316  return ranges[index].maximum;
317 }
318 
319 void (max)(std::size_t const& index, T v)
320 {
321  if (ranges.size() <= index) {
322  ranges.resize(index + 1);
323  }
324  ranges[index].maximum = v;
325 }
326 
327 // liblas::Point (min)() {
328 // liblas::Point p(&DefaultHeader::get());
329 // try
330 // {
331 // p.SetCoordinates(ranges[0].minimum, ranges[1].minimum, ranges[2].minimum);
332 // }
333 // catch (std::runtime_error const& )
334 // {
335 // p.SetCoordinates(ranges[0].minimum, ranges[1].minimum, 0);
336 //
337 // }
338 //
339 // return p;
340 // }
341 //
342 // liblas::Point (max)() {
343 // liblas::Point p(&DefaultHeader::get());
344 // try
345 // {
346 // p.SetCoordinates(ranges[0].maximum, ranges[1].maximum, ranges[2].maximum);
347 // }
348 // catch (std::runtime_error const& )
349 // {
350 // p.SetCoordinates(ranges[0].maximum, ranges[1].maximum, 0);
351 //
352 // }
353 // return p;
354 // }
355 
356 T minx() const { if (ranges.size() == 0) return 0; return ranges[0].minimum; }
357 T miny() const { if (ranges.size() < 2) return 0; return ranges[1].minimum; }
358 T minz() const { if (ranges.size() < 3) return 0; return ranges[2].minimum; }
359 T maxx() const { if (ranges.size() == 0) return 0; return ranges[0].maximum; }
360 T maxy() const { if (ranges.size() < 2) return 0; return ranges[1].maximum; }
361 T maxz() const { if (ranges.size() < 3) return 0; return ranges[2].maximum; }
362 
363 inline bool operator==(Bounds<T> const& rhs) const
364 {
365  return equal(rhs);
366 }
367 
368 inline bool operator!=(Bounds<T> const& rhs) const
369 {
370  return (!equal(rhs));
371 }
372 
373 
375 {
376  if (&rhs != this)
377  {
378  ranges = rhs.ranges;
379  }
380  return *this;
381 }
382 
384 RangeVec const& dims () const { return ranges; }
385 
387 size_type dimension() const
388 {
389  return ranges.size();
390 }
391 
393 void dimension(size_type d)
394 {
395  if (ranges.size() < d) {
396  ranges.resize(d);
397  }
398 }
399 
401 bool equal(Bounds<T> const& other) const
402 {
403  for (size_type i = 0; i < dimension(); i++) {
404  if ( ranges[i] != other.ranges[i] )
405  return false;
406  }
407  return true;
408 }
409 
411 bool intersects(Bounds const& other) const
412 {
413 
414  for (size_type i = 0; i < dimension(); i++) {
415  if ( ranges[i].overlaps(other.ranges[i]) )
416  return true;
417  }
418 
419  return false;
420 
421 }
422 
424 bool overlaps(Bounds const& other) const
425 {
426  return intersects(other);
427 }
428 
430 bool contains(Bounds const& other) const
431 {
432  for (size_type i = 0; i < dimension(); i++) {
433  if ( !ranges[i].contains(other.ranges[i]) )
434  return false; // As soon as it is not contains, we're false
435  }
436  return true;
437 }
438 
440 bool contains(Point const& point) const
441 {
442  // std::cout << ranges[0].length() << std::endl;
443  // std::cout << "x contain: " << ranges[0].contains(point.GetX())
444  // << " r.x.min: " << ranges[0].min
445  // << " r.x.max: " << ranges[0].max
446  // << " p.x: " << point.GetX() << std::endl;
447  // std::cout << "y contain: " << ranges[1].contains(point.GetY())
448  // << " r.y.min: " << ranges[1].min
449  // << " r.y.max: " << ranges[1].max
450  // << " p.y: " << point.GetY() << std::endl;
451  // std::cout << "z contain: " << ranges[2].contains(point.GetZ())
452  // << " r.z.min: " << ranges[2].min
453  // << " r.z.max: " << ranges[2].max
454  // << " p.z: " << point.GetZ() << std::endl;
455  if (!ranges[0].contains(point.GetX()))
456  return false;
457  if (!ranges[1].contains(point.GetY()))
458  return false;
459 
460  // If our z bounds has no length, we'll say it's contained anyway.
461  if (!ranges[2].contains(point.GetZ()))
462  {
463  if (detail::compare_distance(ranges[2].length(), 0.0))
464  return true;
465  return false;
466  }
467  return true;
468 }
470 void shift(std::vector<T> deltas)
471 {
472  typedef typename std::vector< T >::size_type size_type;
473 
474  size_type i;
475  if( dimension() <= deltas.size())
476  {
477  std::ostringstream msg;
478  msg << "liblas::Bounds::shift: Delta vector size, " << deltas.size()
479  << ", is larger than the dimensionality of the bounds, "<< dimension() << ".";
480  throw std::runtime_error(msg.str());
481  }
482  for (i = 0; i < deltas.size(); ++i){
483  ranges[i].shift(deltas[i]);
484  }
485 }
486 
488 void scale(std::vector<T> deltas)
489 {
490  typedef typename std::vector< T >::size_type size_type;
491 
492  size_type i;
493  if( dimension() <= deltas.size())
494  {
495  std::ostringstream msg;
496  msg << "liblas::Bounds::scale: Delta vector size, " << deltas.size()
497  << ", is larger than the dimensionality of the bounds, "<< dimension() << ".";
498  throw std::runtime_error(msg.str());
499  }
500  for (i = 0; i < deltas.size(); ++i){
501  ranges[i].scale(deltas[i]);
502  }
503 }
504 
506 void clip(Bounds const& r)
507 {
508  RangeVec ds = r.dims();
509  for (size_type i = 0; i < dimension(); ++i){
510  ranges[i].clip(ds[i]);
511  }
512 }
513 
515 void grow(Bounds const& r)
516 {
517  RangeVec ds = r.dims();
518  for (size_type i = 0; i < dimension(); ++i){
519  ranges[i].grow(ds[i]);
520  }
521 }
522 
524 void grow(Point const& p)
525 {
526  ranges[0].grow(p.GetX());
527  ranges[1].grow(p.GetY());
528  ranges[2].grow(p.GetZ());
529 }
530 
531 T volume() const
532 {
533  T output = T();
534  for (size_type i = 0; i < dimension(); i++) {
535  output = output * ranges[i].length();
536  }
537 
538  return output;
539 }
540 
541 bool empty() const
542 {
543  for (size_type i = 0; i < dimension(); i++) {
544  if (ranges[i].empty())
545  return true;
546  }
547  return false;
548 }
549 
550 void verify()
551 {
552  for (size_type d = 0; d < dimension(); ++d)
553  {
554  if ((min)(d) > (max)(d) )
555  {
556  // Check that we're not infinity either way
557  if ( (detail::compare_distance((min)(d), (std::numeric_limits<T>::max)()) ||
558  detail::compare_distance((max)(d), -(std::numeric_limits<T>::max)()) ))
559  {
560  std::ostringstream msg;
561  msg << "liblas::Bounds::verify: Minimum point at dimension " << d
562  << "is greater than maximum point. Neither point is infinity.";
563  throw std::runtime_error(msg.str());
564  }
565  }
566  }
567 }
568 
569 // Bounds<T> project(liblas::SpatialReference const& in_ref, liblas::SpatialReference const& out_ref)
570 // {
571 // liblas::ReprojectionTransform trans(in_ref, out_ref);
572 //
573 // liblas::Point minimum = (min)();
574 // liblas::Point maximum = (max)();
575 // trans.transform(minimum);
576 // trans.transform(maximum);
577 // return Bounds<T>(minimum, maximum);
578 // }
579 
580 
581 
582 };
583 
584 
585 
586 } // namespace liblas
587 
588 // Needed for C++ DLL exports
589 #ifdef _MSC_VER
590 template class LAS_DLL liblas::Range<double>;
591 template class LAS_DLL liblas::Bounds<double>;
592 #endif
593 
594 #endif // ndef LIBLAS_LASBOUNDS_HPP_INCLUDED
void scale(T v)
Definition: bounds.hpp:140
std::vector< Range< T > > RangeVec
Definition: bounds.hpp:182
void scale(std::vector< T > deltas)
Scale each dimension by a vector of deltas.
Definition: bounds.hpp:488
Bounds(RangeVec const &rngs)
Definition: bounds.hpp:200
bool contains(Bounds const &other) const
Does this Bounds contain other?
Definition: bounds.hpp:430
#define LAS_DLL
Definition: export.hpp:58
bool contains(T v) const
Definition: bounds.hpp:124
bool operator!=(Range const &rhs) const
Definition: bounds.hpp:97
Range(Range const &other)
Definition: bounds.hpp:76
T minimum
Definition: bounds.hpp:67
void grow(Range const &r)
Definition: bounds.hpp:162
bool contains(Point const &point) const
Does this Bounds this point other?
Definition: bounds.hpp:440
std::vector< Range< double > >::size_type size_type
Definition: bounds.hpp:180
T miny() const
Definition: bounds.hpp:357
bool operator==(Bounds< T > const &rhs) const
Definition: bounds.hpp:363
bool equal(Range const &other) const
Definition: bounds.hpp:102
bool empty() const
Definition: bounds.hpp:541
Definition: bounds.hpp:175
Bounds(T minx, T miny, T minz, T maxx, T maxy, T maxz)
Definition: bounds.hpp:206
void grow(T v)
Definition: bounds.hpp:154
double GetX() const
double GetY() const
T maxy() const
Definition: bounds.hpp:360
void grow(Bounds const &r)
Grow to the union of two liblas::Bounds.
Definition: bounds.hpp:515
size_type dimension() const
The number of dimensions of the Bounds.
Definition: bounds.hpp:387
Range & operator=(Range< T > const &rhs)
Definition: bounds.hpp:82
bool intersects(Bounds const &other) const
Does this Bounds intersect other?
Definition: bounds.hpp:411
bool operator!=(Bounds< T > const &rhs) const
Definition: bounds.hpp:368
T value_type
Definition: bounds.hpp:179
Range(T mmin=(std::numeric_limits< T >::max)(), T mmax=(std::numeric_limits< T >::min)())
Definition: bounds.hpp:72
Definition: bounds.hpp:64
T value_type
Definition: bounds.hpp:70
Bounds(T minx, T miny, T maxx, T maxy)
Definition: bounds.hpp:229
void clip(Range const &r)
Definition: bounds.hpp:146
void grow(Point const &p)
Expand the liblas::Bounds to include this point.
Definition: bounds.hpp:524
bool operator==(Range< T > const &rhs) const
Definition: bounds.hpp:92
T maxz() const
Definition: bounds.hpp:361
bool empty(void) const
Definition: bounds.hpp:129
Bounds(Bounds const &other)
Definition: bounds.hpp:194
bool contains(Range const &r) const
Definition: bounds.hpp:119
void shift(T v)
Definition: bounds.hpp:134
void shift(std::vector< T > deltas)
Shift each dimension by a vector of detlas.
Definition: bounds.hpp:470
void clip(Bounds const &r)
Clip this Bounds to the extent of r.
Definition: bounds.hpp:506
T minz() const
Definition: bounds.hpp:358
void dimension(size_type d)
Resize the dimensionality of the Bounds to d.
Definition: bounds.hpp:393
Namespace grouping all elements of libLAS public interface.
Definition: bounds.hpp:60
T volume() const
Definition: bounds.hpp:531
Point data record composed with X, Y, Z coordinates and attributes.
Definition: point.hpp:68
Bounds(const Point &min, const Point &max)
Definition: bounds.hpp:249
double GetZ() const
void verify()
Definition: bounds.hpp:550
Bounds< T > & operator=(Bounds< T > const &rhs)
Definition: bounds.hpp:374
T minx() const
Definition: bounds.hpp:356
T length() const
Definition: bounds.hpp:168
bool overlaps(Bounds const &other) const
Synonym for intersects for now.
Definition: bounds.hpp:424
bool equal(Bounds< T > const &other) const
Is this Bounds equal to other?
Definition: bounds.hpp:401
RangeVec const & dims() const
The vector of Range<T> for the Bounds.
Definition: bounds.hpp:384
bool overlaps(Range const &r) const
Definition: bounds.hpp:114
Definition: schema.hpp:80
T maxx() const
Definition: bounds.hpp:359
T maximum
Definition: bounds.hpp:68