1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5'use strict';
6
7/**
8 * @fileoverview 2D bounding box computations.
9 */
10base.require('base.gl_matrix');
11base.require('base.rect');
12
13base.exportTo('base', function() {
14
15  /**
16   * Tracks a 2D bounding box.
17   * @constructor
18   */
19  function BBox2() {
20    this.isEmpty_ = true;
21    this.min_ = undefined;
22    this.max_ = undefined;
23  };
24
25  BBox2.prototype = {
26    __proto__: Object.prototype,
27
28    reset: function() {
29      this.isEmpty_ = true;
30      this.min_ = undefined;
31      this.max_ = undefined;
32    },
33
34    get isEmpty() {
35      return this.isEmpty_;
36    },
37
38    addBBox2: function(bbox2) {
39      if (bbox2.isEmpty)
40        return;
41      this.addVec2(bbox2.min_);
42      this.addVec2(bbox2.max_);
43    },
44
45    clone: function() {
46      var bbox = new BBox2();
47      bbox.addBBox2(this);
48      return bbox;
49    },
50
51    /**
52     * Adds x, y to the range.
53     */
54    addXY: function(x, y) {
55      if (this.isEmpty_) {
56        this.max_ = vec2.create();
57        this.min_ = vec2.create();
58        vec2.set(this.max_, x, y);
59        vec2.set(this.min_, x, y);
60        this.isEmpty_ = false;
61        return;
62      }
63      this.max_[0] = Math.max(this.max_[0], x);
64      this.max_[1] = Math.max(this.max_[1], y);
65      this.min_[0] = Math.min(this.min_[0], x);
66      this.min_[1] = Math.min(this.min_[1], y);
67    },
68
69    /**
70     * Adds value_x, value_y in the form [value_x,value_y] to the range.
71     */
72    addVec2: function(value) {
73      if (this.isEmpty_) {
74        this.max_ = vec2.create();
75        this.min_ = vec2.create();
76        vec2.set(this.max_, value[0], value[1]);
77        vec2.set(this.min_, value[0], value[1]);
78        this.isEmpty_ = false;
79        return;
80      }
81      this.max_[0] = Math.max(this.max_[0], value[0]);
82      this.max_[1] = Math.max(this.max_[1], value[1]);
83      this.min_[0] = Math.min(this.min_[0], value[0]);
84      this.min_[1] = Math.min(this.min_[1], value[1]);
85    },
86
87    addQuad: function(quad) {
88      this.addVec2(quad.p1);
89      this.addVec2(quad.p2);
90      this.addVec2(quad.p3);
91      this.addVec2(quad.p4);
92    },
93
94    get minVec2() {
95      if (this.isEmpty_)
96        return undefined;
97      return this.min_;
98    },
99
100    get maxVec2() {
101      if (this.isEmpty_)
102        return undefined;
103      return this.max_;
104    },
105
106    get sizeAsVec2() {
107      if (this.isEmpty_)
108        throw new Error('Empty BBox2 has no size');
109      var size = vec2.create();
110      vec2.subtract(size, this.max_, this.min_);
111      return size;
112    },
113
114    get size() {
115      if (this.isEmpty_)
116        throw new Error('Empty BBox2 has no size');
117      return {width: this.max_[0] - this.min_[0],
118        height: this.max_[1] - this.min_[1]};
119    },
120
121    get width() {
122      if (this.isEmpty_)
123        throw new Error('Empty BBox2 has no width');
124      return this.max_[0] - this.min_[0];
125    },
126
127    get height() {
128      if (this.isEmpty_)
129        throw new Error('Empty BBox2 has no width');
130      return this.max_[1] - this.min_[1];
131    },
132
133    toString: function() {
134      if (this.isEmpty_)
135        return 'empty';
136      return 'min=(' + this.min_[0] + ',' + this.min_[1] + ') ' +
137          'max=(' + this.max_[0] + ',' + this.max_[1] + ')';
138    },
139
140    asRect: function() {
141      return base.Rect.FromXYWH(
142          this.min_[0],
143          this.min_[1],
144          this.max_[0] - this.min_[0],
145          this.max_[1] - this.min_[1]);
146    }
147  };
148
149  return {
150    BBox2: BBox2
151  };
152
153});
154