Class: PhotoUtils::SceneView

Inherits:
Object
  • Object
show all
Defined in:
lib/photo_utils/scene_view.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(scene, options = {}) ⇒ SceneView

Returns a new instance of SceneView.



15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/photo_utils/scene_view.rb', line 15

def initialize(scene, options={})
  @scene = scene
  @width = options[:width] || 900
  @height = options[:height] || 50
  @max_distance = options[:max_distance] || @scene.depth_of_field.far
  @camera_width  = options[:camera_width]  || @scene.focal_length
  @camera_height = options[:camera_height] || [@scene.absolute_aperture, @scene.format.height].max
  @scale = (@width.to_f - @height) / (@camera_width + @max_distance)
  @camera_scale = [
    @height.to_f / @camera_width,
    @height.to_f / @camera_height
  ].min
end

Instance Attribute Details

#camera_heightObject

Returns the value of attribute camera_height.



12
13
14
# File 'lib/photo_utils/scene_view.rb', line 12

def camera_height
  @camera_height
end

#camera_widthObject

Returns the value of attribute camera_width.



11
12
13
# File 'lib/photo_utils/scene_view.rb', line 11

def camera_width
  @camera_width
end

#heightObject

Returns the value of attribute height.



9
10
11
# File 'lib/photo_utils/scene_view.rb', line 9

def height
  @height
end

#max_distanceObject

Returns the value of attribute max_distance.



10
11
12
# File 'lib/photo_utils/scene_view.rb', line 10

def max_distance
  @max_distance
end

#scaleObject

Returns the value of attribute scale.



13
14
15
# File 'lib/photo_utils/scene_view.rb', line 13

def scale
  @scale
end

#sceneObject

Returns the value of attribute scene.



7
8
9
# File 'lib/photo_utils/scene_view.rb', line 7

def scene
  @scene
end

#widthObject

Returns the value of attribute width.



8
9
10
# File 'lib/photo_utils/scene_view.rb', line 8

def width
  @width
end

Instance Method Details

#draw_camera(xml) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/photo_utils/scene_view.rb', line 49

def draw_camera(xml)
  fh2 = (@scene.format.height / 2) * @camera_scale
  aa2 = (@scene.absolute_aperture / 2) * @camera_scale
  points = [
    [0, -fh2],
    [@scene.focal_length * @camera_scale, -aa2],
    [@scene.focal_length * @camera_scale, aa2],
    [0, fh2],
  ]
  xml.g(transform: "translate(0,#{@height / 2})") do
    xml.polygon(
      x: -@height,
      y: 0,
      points: points.map { |p| p.join(',') }.join(' '),
      fill: 'black')
  end
end

#draw_dof(xml) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/photo_utils/scene_view.rb', line 67

def draw_dof(xml)
  # blur

  if true

    step = @max_distance / 20
    step.step(@max_distance, step).map { |d| Length.new(d) }.each do |d|
      blur = @scene.blur_at_distance(d)
      if blur == 0
        std_dev = 0
      else
        ratio = @scene.circle_of_confusion / blur
        std_dev = [9 - (ratio * 10).to_i, 0].max
      end
      xml.circle(
        cx: d * @scale,
        cy: @height / 2,
        r: (step * @scale) / 2 / 2,
        fill: 'black',
        filter: (std_dev > 0) ? "url(\#gb#{std_dev})" : ())
    end

  else
    step = (@max_distance / @width) * 10
    0.step(@max_distance, step).map { |d| Length.new(d) }.each do |distance|
      blur = @scene.blur_at_distance(distance)
      opacity = [1, @scene.circle_of_confusion / blur].min
      xml.rect(
        x: distance * @scale,
        y: (@height - (@scene.field_of_view(distance).height * @scale)) / 2,
        width: step * @scale,
        height: @scene.field_of_view(distance).height * @scale,
        fill: 'blue',
        'fill-opacity' => opacity)
    end
  end

  # depth of focus area
  xml.rect(
    x: @scene.depth_of_field.near * @scale,
    y: 0,
    width: @scene.total_depth_of_field * @scale,
    height: @height,
    stroke: 'blue',
    fill: 'none')
end

#draw_hyperfocal(xml) ⇒ Object



123
124
125
126
127
128
129
130
# File 'lib/photo_utils/scene_view.rb', line 123

def draw_hyperfocal(xml)
  xml.line(
    x1: @scene.hyperfocal_distance * scale,
    y1: 0,
    x2: @scene.hyperfocal_distance * scale,
    y2: @height,
    stroke: 'green')
end

#draw_subject(xml) ⇒ Object



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

def draw_subject(xml)
  xml.rect(
    x: @scene.subject_distance * @scale,
    y: 0,
    width: 1,
    height: @height,
    fill: 'red')
end

#to_svgObject



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/photo_utils/scene_view.rb', line 29

def to_svg
  xml = Builder::XmlMarkup.new(indent: 2)
  xml.svg(width: @width, height: @height) do
    xml.defs do
      1.upto(9).each do |std_dev|
        xml.filter(id: "gb#{std_dev}") do
          xml.feGaussianBlur(in: 'SourceGraphic', stdDeviation: std_dev)
        end
      end
    end
    xml.g(transform: "translate(#{@height},0)") do
      draw_camera(xml)
      draw_dof(xml)
      draw_subject(xml)
      # draw_hyperfocal(xml)
    end
  end
  xml.target!
end