Class: Autocad::BoundingBox

Inherits:
Object
  • Object
show all
Defined in:
lib/autocad/bounding_box.rb

Overview

A BoundingBox represents a bounding box around a picture.

A bounding box also defines a local coordinate system for a picture. The bounding box must contain the origin of the coordinate system. However the origin need not be centered within the box.

No particular guarantees are made about the tightness of the bounding box, though it can assumed to be reasonably tight.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(left, top, right, bottom) ⇒ BoundingBox

Returns a new instance of BoundingBox.



40
41
42
43
44
45
# File 'lib/autocad/bounding_box.rb', line 40

def initialize(left, top, right, bottom)
  @left = left
  @top = top
  @right = right
  @bottom = bottom
end

Instance Attribute Details

#bottomObject (readonly)

Returns the value of attribute bottom.



38
39
40
# File 'lib/autocad/bounding_box.rb', line 38

def bottom
  @bottom
end

#leftObject (readonly)

Returns the value of attribute left.



38
39
40
# File 'lib/autocad/bounding_box.rb', line 38

def left
  @left
end

#rightObject (readonly)

Returns the value of attribute right.



38
39
40
# File 'lib/autocad/bounding_box.rb', line 38

def right
  @right
end

#topObject (readonly)

Returns the value of attribute top.



38
39
40
# File 'lib/autocad/bounding_box.rb', line 38

def top
  @top
end

Class Method Details

.centered(width, height) ⇒ Object

Create a BoundingBox with the given width and height and the origin centered within the box.



18
19
20
21
22
# File 'lib/autocad/bounding_box.rb', line 18

def centered(width, height)
  w = width / 2.0
  h = height / 2.0
  new(-w, h, w, -h)
end

.emptyObject



12
13
14
# File 'lib/autocad/bounding_box.rb', line 12

def empty
  new(0, 0, 0, 0)
end

.from_min_max(min_pt, max_pt) ⇒ Object

Create a BoundingBox from minimum and maximum points



25
26
27
28
29
30
31
32
33
34
35
# File 'lib/autocad/bounding_box.rb', line 25

def from_min_max(min_pt, max_pt)
  min_pt = Point3d.new(min_pt)
  max_pt = Point3d.new(max_pt)

  new(
    min_pt.x,  # left
    max_pt.y,  # top
    max_pt.x,  # right
    min_pt.y   # bottom
  )
end

Instance Method Details

#==(other) ⇒ Object



59
60
61
62
63
64
65
66
# File 'lib/autocad/bounding_box.rb', line 59

def ==(other)
  return false unless other.is_a?(BoundingBox)

  left.round(6) == other.left.round(6) &&
    top.round(6) == other.top.round(6) &&
    right.round(6) == other.right.round(6) &&
    bottom.round(6) == other.bottom.round(6)
end

#above(other) ⇒ Object



114
115
116
117
118
119
120
121
# File 'lib/autocad/bounding_box.rb', line 114

def above(other)
  self.class.new(
    [left, other.left].min,
    (height + other.height) / 2.0,
    [right, other.right].max,
    -(height + other.height) / 2.0
  )
end

#at(point) ⇒ Object



133
134
135
136
137
138
139
140
141
142
143
# File 'lib/autocad/bounding_box.rb', line 133

def at(point)
  x = point.x
  y = point.y

  new_left = [left + x, 0].min
  new_top = [top + y, 0].max
  new_right = [right + x, 0].max
  new_bottom = [bottom + y, 0].min

  self.class.new(new_left, new_top, new_right, new_bottom)
end

#at_landmark(landmark) ⇒ Object



145
146
147
# File 'lib/autocad/bounding_box.rb', line 145

def at_landmark(landmark)
  at(eval(landmark))
end

#beside(other) ⇒ Object



105
106
107
108
109
110
111
112
# File 'lib/autocad/bounding_box.rb', line 105

def beside(other)
  self.class.new(
    -(width + other.width) / 2.0,
    [top, other.top].max,
    (width + other.width) / 2.0,
    [bottom, other.bottom].min
  )
end

#centerObject



80
81
82
# File 'lib/autocad/bounding_box.rb', line 80

def center
  Point3d.new((left + right) / 2.0, (top + bottom) / 2.0, 0)
end

#contains?(pt) ⇒ Boolean

Returns:

  • (Boolean)


84
85
86
# File 'lib/autocad/bounding_box.rb', line 84

def contains?(pt)
  pt.x >= left && pt.x <= right && pt.y >= bottom && pt.y <= top
end

#enclose(point) ⇒ Object

Expand bounding box to enclose the given Point



169
170
171
172
173
174
175
176
# File 'lib/autocad/bounding_box.rb', line 169

def enclose(point)
  self.class.new(
    [left, point.x].min,
    [top, point.y].max,
    [right, point.x].max,
    [bottom, point.y].min
  )
end

#eql?(other) ⇒ Boolean

Returns:

  • (Boolean)


51
52
53
54
55
56
57
# File 'lib/autocad/bounding_box.rb', line 51

def eql?(other)
  other.class == self.class &&
    other.left == left &&
    other.top == top &&
    other.right == right &&
    other.bottom == bottom
end

#eval(landmark) ⇒ Object

Evaluate the landmark relative to the origin of this bounding box, returning the location described by the landmark.



125
126
127
128
129
130
131
# File 'lib/autocad/bounding_box.rb', line 125

def eval(landmark)
  Point3d.new(
    landmark.x.eval(left, right),
    landmark.y.eval(bottom, top),
    0
  )
end

#expand(expansion) ⇒ Object

Add expansion to all sides of this bounding box



185
186
187
188
189
190
191
192
# File 'lib/autocad/bounding_box.rb', line 185

def expand(expansion)
  self.class.new(
    left - expansion,
    top + expansion,
    right + expansion,
    bottom - expansion
  )
end

#hashObject



47
48
49
# File 'lib/autocad/bounding_box.rb', line 47

def hash
  [self.class, left, top, right, bottom].hash
end

#heightObject



92
93
94
# File 'lib/autocad/bounding_box.rb', line 92

def height
  top - bottom
end

#lower_leftObject Also known as: bottom_left



74
75
76
# File 'lib/autocad/bounding_box.rb', line 74

def lower_left
  Point3d.new(left, bottom, 0)
end

#on(other) ⇒ Object



96
97
98
99
100
101
102
103
# File 'lib/autocad/bounding_box.rb', line 96

def on(other)
  self.class.new(
    [left, other.left].min,
    [top, other.top].max,
    [right, other.right].max,
    [bottom, other.bottom].min
  )
end

#origin_at(point) ⇒ Object



149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/autocad/bounding_box.rb', line 149

def origin_at(point)
  # Vector maths to work out where the edges of the bounding box lie in
  # relation to the new origin
  new_top_left = Point3d.new(left, top, 0) - point
  new_bottom_right = Point3d.new(right, bottom, 0) - point

  # Make sure the bounding box includes the origin
  new_left = [new_top_left.x, 0].min
  new_top = [new_top_left.y, 0].max
  new_right = [new_bottom_right.x, 0].max
  new_bottom = [new_bottom_right.y, 0].min

  self.class.new(new_left, new_top, new_right, new_bottom)
end

#origin_at_landmark(landmark) ⇒ Object



164
165
166
# File 'lib/autocad/bounding_box.rb', line 164

def origin_at_landmark(landmark)
  origin_at(eval(landmark))
end

#scale_to_fit(bb) ⇒ Object



178
179
180
181
182
# File 'lib/autocad/bounding_box.rb', line 178

def scale_to_fit(bb)
  return 1 if bb.width == 0 || bb.height == 0

  [width / bb.width, height / bb.height].min
end

#transform(transform) ⇒ Object



194
195
196
197
198
199
200
# File 'lib/autocad/bounding_box.rb', line 194

def transform(transform)
  self.class.empty
    .enclose(transform.call(Point3d.new(left, top, 0)))
    .enclose(transform.call(Point3d.new(right, top, 0)))
    .enclose(transform.call(Point3d.new(left, bottom, 0)))
    .enclose(transform.call(Point3d.new(right, bottom, 0)))
end

#upper_rightObject Also known as: top_right



68
69
70
# File 'lib/autocad/bounding_box.rb', line 68

def upper_right
  Point3d.new(right, top, 0)
end

#widthObject



88
89
90
# File 'lib/autocad/bounding_box.rb', line 88

def width
  right - left
end