dudegl 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/compose/arms.rb +41 -0
- data/lib/compose/body.rb +51 -0
- data/lib/compose/dudes_location.rb +48 -0
- data/lib/compose/legs.rb +25 -0
- data/lib/compose/limbs.rb +30 -0
- data/lib/config.rb +16 -4
- data/lib/dudegl.rb +31 -11
- data/lib/limbs/arm.rb +72 -0
- data/lib/limbs/leg.rb +41 -0
- data/lib/limbs/limb.rb +33 -0
- data/lib/render.rb +59 -0
- data/lib/utils.rb +4 -12
- metadata +11 -4
- data/lib/arm.rb +0 -80
- data/lib/dude.rb +0 -40
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 629bfb1702e517a1bf3f5f52fbf5b3c8eb7e82919cd122aadee7ffa494f35979
|
|
4
|
+
data.tar.gz: fa4395ff7d805a91016f9a384cb2928d7c777e84600e3ff473ff562c02eda072
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a4531659105ee4b4e53cb098ddae20c75eb51bfc5175ace477dc2c705c8f435d2102c91347d789b45534f8dea6d12433130f929f51849094eb387a8b2196d76a
|
|
7
|
+
data.tar.gz: f2a4f167a1b012c647056ab937029eb9887c34184be036ce7d382f5235999b799ff97fc34f71602808420a4bc0620ca0fa9b174ff14e596610d8941a9938fcd3
|
data/lib/compose/arms.rb
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
require_relative '../config'
|
|
2
|
+
require_relative 'limbs'
|
|
3
|
+
|
|
4
|
+
class Arms < Limbs
|
|
5
|
+
|
|
6
|
+
private
|
|
7
|
+
|
|
8
|
+
def draw
|
|
9
|
+
super
|
|
10
|
+
divide_arms
|
|
11
|
+
|
|
12
|
+
@left_arms_num.times do |i|
|
|
13
|
+
@limbs << Arm.new(@left_arms[i], @body.body_left_x, hy(i), :left)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
@right_arms_num.times do |i|
|
|
17
|
+
@limbs << Arm.new(@right_arms[i], @body.body_right_x, hy(i), :right)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def draw_parameters
|
|
22
|
+
return if super
|
|
23
|
+
|
|
24
|
+
remainder = @limbs_num % 2
|
|
25
|
+
|
|
26
|
+
@left_arms_num = (@limbs_num - remainder) / 2 + remainder
|
|
27
|
+
@right_arms_num = @limbs_num - @left_arms_num
|
|
28
|
+
|
|
29
|
+
# BODY_LENGTH * 0.9 - to avoid drawing hands on a body edges
|
|
30
|
+
@arms_step = ((Config::BODY_LENGTH * 0.9) / @left_arms_num).round
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def divide_arms
|
|
34
|
+
@left_arms = @params_methods[0, @left_arms_num]
|
|
35
|
+
@right_arms = @params_methods[@left_arms_num, @limbs_num]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def hy(i)
|
|
39
|
+
(1.05 * @body.body_left_top_y + i * @arms_step).round
|
|
40
|
+
end
|
|
41
|
+
end
|
data/lib/compose/body.rb
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
require_relative '../utils'
|
|
2
|
+
require_relative '../config'
|
|
3
|
+
|
|
4
|
+
class Body
|
|
5
|
+
include Utils
|
|
6
|
+
|
|
7
|
+
attr_reader :body_right_x, :body_right_top_y,
|
|
8
|
+
:body_left_x, :body_left_top_y, :draw_data
|
|
9
|
+
|
|
10
|
+
def initialize(name, offsets)
|
|
11
|
+
@name = name
|
|
12
|
+
@draw_data = []
|
|
13
|
+
@offset_x = offsets[:offset_x]
|
|
14
|
+
@offset_y = offsets[:offset_y]
|
|
15
|
+
draw_body
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def draw_body
|
|
19
|
+
# head center
|
|
20
|
+
head_center_x = 0.5 * Config::DUDE_FRAME_SIZE + @offset_x
|
|
21
|
+
head_center_y = 0.3 * Config::DUDE_FRAME_SIZE + @offset_y
|
|
22
|
+
|
|
23
|
+
@body_right_x, @body_right_top_y = circle_rotate(head_center_x, head_center_y,
|
|
24
|
+
Config::HEAD_RADIUS,
|
|
25
|
+
Config::BODY_CENTER + Config::SLIM_FACTOR)
|
|
26
|
+
@body_left_x, @body_left_top_y = circle_rotate(head_center_x, head_center_y,
|
|
27
|
+
Config::HEAD_RADIUS,
|
|
28
|
+
Config::BODY_CENTER - Config::SLIM_FACTOR)
|
|
29
|
+
|
|
30
|
+
@draw_data << {
|
|
31
|
+
circle: {
|
|
32
|
+
cx: head_center_x,
|
|
33
|
+
cy: head_center_y,
|
|
34
|
+
r: Config::HEAD_RADIUS
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@draw_data << draw_line(@body_right_x, @body_right_top_y,
|
|
39
|
+
@body_right_x, @body_right_top_y + Config::BODY_LENGTH)
|
|
40
|
+
# left part of a body
|
|
41
|
+
@draw_data << draw_line(@body_left_x, @body_left_top_y,
|
|
42
|
+
@body_left_x, @body_left_top_y + Config::BODY_LENGTH)
|
|
43
|
+
# bottom
|
|
44
|
+
@draw_data << draw_line(@body_right_x, @body_right_top_y + Config::BODY_LENGTH,
|
|
45
|
+
@body_left_x, @body_left_top_y + Config::BODY_LENGTH)
|
|
46
|
+
|
|
47
|
+
@draw_data << draw_caption(@name, head_center_x - Config::HEAD_RADIUS,
|
|
48
|
+
head_center_y - 1.1 * Config::HEAD_RADIUS,
|
|
49
|
+
font_size: 10)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
require_relative '../config'
|
|
2
|
+
|
|
3
|
+
# arrange several dudes on canvas
|
|
4
|
+
class DudesLocation
|
|
5
|
+
attr_reader :offsets, :canvas_size_x, :canvas_size_y
|
|
6
|
+
|
|
7
|
+
def initialize(params_list, dudes_per_row_max = nil)
|
|
8
|
+
@dudes_num = params_list.size
|
|
9
|
+
@offsets = []
|
|
10
|
+
|
|
11
|
+
if dudes_per_row_max.nil?
|
|
12
|
+
@dudes_per_row_max = Config::DUDES_PER_ROW_MAX
|
|
13
|
+
else
|
|
14
|
+
@dudes_per_row_max = dudes_per_row_max
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
compute_dudes_coordiantes
|
|
18
|
+
compute_canvas_size
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
# returns array with number of dudes in each row
|
|
24
|
+
# e.g. if we have 12 dudes and only 5 are allowed per row, then the output will be [5, 5, 2])
|
|
25
|
+
def compute_dudes_per_each_row
|
|
26
|
+
remaining_dudes = @dudes_num % @dudes_per_row_max
|
|
27
|
+
rows_num = (@dudes_num - remaining_dudes) / @dudes_per_row_max
|
|
28
|
+
full_rows = [@dudes_per_row_max] * rows_num
|
|
29
|
+
remaining_dudes > 0 ? full_rows + [remaining_dudes]: full_rows
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def compute_dudes_coordiantes
|
|
33
|
+
@dudes_per_each_row = compute_dudes_per_each_row
|
|
34
|
+
offset_y = 0
|
|
35
|
+
@dudes_per_each_row.each_with_index do |dudes_in_row, y_index|
|
|
36
|
+
dudes_in_row.times do |x_index|
|
|
37
|
+
@offsets << { offset_x: x_index * Config::OFFSET_X, offset_y: y_index * Config::OFFSET_Y }
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def compute_canvas_size
|
|
43
|
+
# max x size of canvas is x offset for the last dude in 1st row - @dudes_per_each_row.first - 1
|
|
44
|
+
# @offsets.last[:offset_y] - last dude has max y offset
|
|
45
|
+
@canvas_size_x = @offsets[@dudes_per_each_row.first - 1][:offset_x] + Config::DUDE_FRAME_SIZE
|
|
46
|
+
@canvas_size_y = @offsets.last[:offset_y] + Config::DUDE_FRAME_SIZE
|
|
47
|
+
end
|
|
48
|
+
end
|
data/lib/compose/legs.rb
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require_relative '../config'
|
|
2
|
+
require_relative 'limbs'
|
|
3
|
+
|
|
4
|
+
class Legs < Limbs
|
|
5
|
+
|
|
6
|
+
private
|
|
7
|
+
|
|
8
|
+
def draw
|
|
9
|
+
super
|
|
10
|
+
|
|
11
|
+
@limbs_num.times do |i|
|
|
12
|
+
@limbs << Leg.new(@params_methods[i], hx(i), @body.body_right_top_y + Config::BODY_LENGTH)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def draw_parameters
|
|
17
|
+
return if super
|
|
18
|
+
@legs_step = (((@body.body_right_x - @body.body_left_x) * 0.9) / @limbs_num).round
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def hx(i)
|
|
22
|
+
body_margin = (@body.body_right_x - @body.body_left_x) * 0.1
|
|
23
|
+
(@body.body_left_x + i * @legs_step + body_margin).round
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require_relative '../config'
|
|
2
|
+
|
|
3
|
+
class Limbs
|
|
4
|
+
attr_reader :limbs
|
|
5
|
+
|
|
6
|
+
def initialize(params, body)
|
|
7
|
+
@params = params
|
|
8
|
+
@body = body
|
|
9
|
+
@limbs = []
|
|
10
|
+
|
|
11
|
+
draw_parameters
|
|
12
|
+
draw if @limbs_num.positive?
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def draw; end
|
|
18
|
+
|
|
19
|
+
def draw_parameters
|
|
20
|
+
@params_methods = @params[:methods].select { |param| param[:args].public_send(select_operator, 0) }
|
|
21
|
+
@limbs_num = @params_methods.size
|
|
22
|
+
return true if @limbs_num == 0
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# dynamically select operator depending on a child class name
|
|
26
|
+
def select_operator
|
|
27
|
+
return '>' if self.class.name.downcase.include?('arm')
|
|
28
|
+
return '==' if self.class.name.downcase.include?('leg')
|
|
29
|
+
end
|
|
30
|
+
end
|
data/lib/config.rb
CHANGED
|
@@ -1,18 +1,30 @@
|
|
|
1
1
|
module Config
|
|
2
|
-
STYLE = { stroke: 'black', stroke_width: 1 }
|
|
3
2
|
IMAGE_DIR = 'images'
|
|
4
3
|
|
|
4
|
+
METHOD_LENGTH_OK_MAX = 5
|
|
5
|
+
|
|
6
|
+
# dude's parameters
|
|
5
7
|
BODY_LENGTH = 140
|
|
6
8
|
BODY_CENTER = Math::PI * (3 / 2.0)
|
|
7
9
|
# defines how slim is a body
|
|
8
10
|
SLIM_FACTOR = Math::PI * (2 / 8.0)
|
|
9
11
|
HEAD_RADIUS = 40
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
ARM_LENGTH_LONG = 70
|
|
13
|
+
LIMB_LENGTH = 40
|
|
14
|
+
LIMB_LENGTH_LONG = 70
|
|
14
15
|
ELLIPSE_LENGTH = 10
|
|
15
16
|
|
|
16
17
|
FINGER_LENGTH = 10
|
|
17
18
|
FINGER_ANGLE_START = Math::PI * (3 / 4.0)
|
|
19
|
+
FINGERS_RANGE = Math::PI / 2.0
|
|
20
|
+
|
|
21
|
+
# size of an square area in pixels where one dude is depicted
|
|
22
|
+
DUDE_FRAME_SIZE = 400
|
|
23
|
+
|
|
24
|
+
# for LocateDudes class
|
|
25
|
+
DUDES_PER_ROW_MAX = 6
|
|
26
|
+
|
|
27
|
+
# coordinates offset for drawing multiple dudes on a canvas
|
|
28
|
+
OFFSET_X = 0.7 * DUDE_FRAME_SIZE
|
|
29
|
+
OFFSET_Y = 0.8 * DUDE_FRAME_SIZE
|
|
18
30
|
end
|
data/lib/dudegl.rb
CHANGED
|
@@ -1,21 +1,41 @@
|
|
|
1
|
-
require '
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
require 'byebug'
|
|
2
|
+
# require all filder from current dir and subdirectories
|
|
3
|
+
Dir[File.dirname(__FILE__) + '/**/*.rb'].each {|file| require_relative file }
|
|
4
4
|
|
|
5
5
|
class DudeGl
|
|
6
|
-
def
|
|
7
|
-
@
|
|
6
|
+
def initialize(params_list, dudes_per_row_max = nil)
|
|
7
|
+
@params_list = params_list
|
|
8
|
+
@dudes = []
|
|
9
|
+
@locations = DudesLocation.new(@params_list, dudes_per_row_max)
|
|
10
|
+
|
|
11
|
+
build_dudes
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def render
|
|
15
|
+
@svg = Render.new(@dudes.flatten,
|
|
16
|
+
width = @locations.canvas_size_x,
|
|
17
|
+
height = @locations.canvas_size_y)
|
|
8
18
|
end
|
|
9
19
|
|
|
10
|
-
def
|
|
11
|
-
|
|
20
|
+
def save(file_name)
|
|
21
|
+
File.open("images/#{file_name}.svg", 'w') { |file| file.write(@svg.contents) }
|
|
12
22
|
end
|
|
13
23
|
|
|
14
|
-
|
|
15
|
-
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def build_dudes
|
|
27
|
+
@params_list.each_with_index { |params, index| @dudes << build_dude(params, index) }
|
|
16
28
|
end
|
|
17
29
|
|
|
18
|
-
def
|
|
19
|
-
@
|
|
30
|
+
def build_dude(params, index)
|
|
31
|
+
body = Body.new(params[:name], offsets = @locations.offsets[index])
|
|
32
|
+
|
|
33
|
+
arms = Arms.new(params, body).limbs
|
|
34
|
+
arms_draw_params = arms.map { |arm| arm.draw_data }
|
|
35
|
+
|
|
36
|
+
legs = Legs.new(params, body).limbs
|
|
37
|
+
legs_draw_params = legs.map { |leg| leg.draw_data }
|
|
38
|
+
|
|
39
|
+
(body.draw_data + arms_draw_params + legs_draw_params).flatten
|
|
20
40
|
end
|
|
21
41
|
end
|
data/lib/limbs/arm.rb
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
require_relative 'limb'
|
|
2
|
+
|
|
3
|
+
class Arm < Limb
|
|
4
|
+
attr_reader :body_side
|
|
5
|
+
|
|
6
|
+
def initialize(params, x0, y0, body_side)
|
|
7
|
+
@body_side = body_side
|
|
8
|
+
super(params, x0, y0)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
def draw
|
|
14
|
+
super
|
|
15
|
+
@end_x = @x0 + @limb_length
|
|
16
|
+
|
|
17
|
+
if @params[:conditions].positive?
|
|
18
|
+
draw_conditions
|
|
19
|
+
else
|
|
20
|
+
@draw_data << draw_line(@x0, @y0, @x0 + @limb_length, @y0)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
@draw_data << draw_caption(@params[:name], (@end_x - 20).round, (@y0 - 10).round)
|
|
24
|
+
draw_fingers(@params[:args])
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def draw_conditions
|
|
28
|
+
@lines_num = @params[:conditions] + 1
|
|
29
|
+
@line_length = ((@limb_length.abs - @params[:conditions] * Config::ELLIPSE_LENGTH) / @lines_num).round
|
|
30
|
+
|
|
31
|
+
@x1 = @x0 + @line_length * orientation
|
|
32
|
+
|
|
33
|
+
@lines_num.times { |i| draw_condition(i) }
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def draw_condition(i)
|
|
37
|
+
@draw_data << draw_line(@x0, @y0, @x1, @y0)
|
|
38
|
+
|
|
39
|
+
@draw_data << { ellipse: {
|
|
40
|
+
cx: (@x1 + Config::ELLIPSE_LENGTH * orientation / 2).round,
|
|
41
|
+
cy: @y0, rx: (Config::ELLIPSE_LENGTH / 2).round,
|
|
42
|
+
ry: (Config::ELLIPSE_LENGTH / 4).round }} if i < @lines_num - 1
|
|
43
|
+
|
|
44
|
+
@x0 += (@line_length + Config::ELLIPSE_LENGTH) * orientation
|
|
45
|
+
@x1 = @x0 + @line_length * orientation
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def draw_fingers(args_num)
|
|
49
|
+
if body_side == :left
|
|
50
|
+
finger_angle_start = Config::FINGER_ANGLE_START
|
|
51
|
+
finger_angle_end = finger_angle_start + Config::FINGERS_RANGE
|
|
52
|
+
finger_angle_step = calc_fingers_range(Config::FINGERS_RANGE, args_num)
|
|
53
|
+
else
|
|
54
|
+
finger_angle_start = - Config::FINGER_ANGLE_START + Math::PI
|
|
55
|
+
finger_angle_end = finger_angle_start - Config::FINGERS_RANGE
|
|
56
|
+
finger_angle_step = - calc_fingers_range(Config::FINGERS_RANGE, args_num)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
args_num.times do |i|
|
|
60
|
+
finger_end_x, finger_end_y = circle_rotate(end_x, end_y, Config::FINGER_LENGTH,
|
|
61
|
+
finger_angle_start + finger_angle_step * i)
|
|
62
|
+
|
|
63
|
+
@draw_data << draw_line(end_x, end_y, finger_end_x, finger_end_y)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def calc_fingers_range(fingers_range, args_num)
|
|
68
|
+
return fingers_range / (args_num - 1).to_f if args_num > 1
|
|
69
|
+
return fingers_range / args_num.to_f if args_num == 1
|
|
70
|
+
return 0
|
|
71
|
+
end
|
|
72
|
+
end
|
data/lib/limbs/leg.rb
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
require_relative 'limb'
|
|
2
|
+
|
|
3
|
+
class Leg < Limb
|
|
4
|
+
|
|
5
|
+
private
|
|
6
|
+
|
|
7
|
+
def draw
|
|
8
|
+
super
|
|
9
|
+
caption_start_x = @x0
|
|
10
|
+
caption_y_start = @y0
|
|
11
|
+
|
|
12
|
+
if @params[:conditions].positive?
|
|
13
|
+
draw_conditions
|
|
14
|
+
else
|
|
15
|
+
@draw_data << draw_line(@x0, @y0, @x0, @y0 + @limb_length)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
@draw_data << draw_caption(@params[:name], (caption_start_x + 10).round, (caption_y_start + 10).round, 9, :tb)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def draw_conditions
|
|
22
|
+
@lines_num = @params[:conditions] + 1
|
|
23
|
+
@line_length = ((@limb_length.abs - @params[:conditions] * Config::ELLIPSE_LENGTH) / @lines_num).round
|
|
24
|
+
|
|
25
|
+
@y1 = @y0 + @line_length
|
|
26
|
+
|
|
27
|
+
@lines_num.times { |i| draw_condition(i) }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def draw_condition(i)
|
|
31
|
+
@draw_data << draw_line(@x0, @y0, @x0, @y1)
|
|
32
|
+
|
|
33
|
+
@draw_data << { ellipse: {
|
|
34
|
+
cx: @x0, cy: (@y1 + Config::ELLIPSE_LENGTH / 2).round ,
|
|
35
|
+
rx: (Config::ELLIPSE_LENGTH / 4).round, ry: (Config::ELLIPSE_LENGTH / 2).round
|
|
36
|
+
}} if i < @lines_num - 1
|
|
37
|
+
|
|
38
|
+
@y0 += @line_length + Config::ELLIPSE_LENGTH
|
|
39
|
+
@y1 = @y0 + @line_length
|
|
40
|
+
end
|
|
41
|
+
end
|
data/lib/limbs/limb.rb
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require_relative '../config'
|
|
2
|
+
|
|
3
|
+
class Limb
|
|
4
|
+
include Utils
|
|
5
|
+
|
|
6
|
+
attr_reader :end_x, :end_y, :draw_data
|
|
7
|
+
|
|
8
|
+
def initialize(params, x0, y0)
|
|
9
|
+
@params = params
|
|
10
|
+
@x0 = x0
|
|
11
|
+
@end_y = @y0 = y0
|
|
12
|
+
@draw_data = []
|
|
13
|
+
|
|
14
|
+
draw
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def draw
|
|
20
|
+
@limb_length = compute_limb_length
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def compute_limb_length
|
|
24
|
+
@params[:length] <= Config::METHOD_LENGTH_OK_MAX ? Config::LIMB_LENGTH * orientation : Config::LIMB_LENGTH_LONG * orientation
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def orientation
|
|
28
|
+
return 1 if @body_side.nil?
|
|
29
|
+
@body_side == :left ? -1 : 1
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def draw_conditions; end
|
|
33
|
+
end
|
data/lib/render.rb
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
require_relative 'config'
|
|
2
|
+
|
|
3
|
+
class Render
|
|
4
|
+
attr_reader :contents
|
|
5
|
+
|
|
6
|
+
def initialize(elements, width = Config::DUDE_FRAME_SIZE, height = Config::DUDE_FRAME_SIZE)
|
|
7
|
+
code = []
|
|
8
|
+
code << %Q[<svg width="#{width}" height="#{height}" style="background:white" xmlns="http://www.w3.org/2000/svg">]
|
|
9
|
+
elements.each { |element| code << hash_to_svg(element) }
|
|
10
|
+
code << %Q[</svg>]
|
|
11
|
+
|
|
12
|
+
@contents = code.join("\n")
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def hash_to_svg(hash)
|
|
18
|
+
operator, params = hash.first
|
|
19
|
+
send("svg_#{operator.to_s}".to_sym, params) if defined? operator
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def svg_line(params)
|
|
23
|
+
<<~LINE.gsub(/\s+/, " ").strip
|
|
24
|
+
<line x1="#{params[:x1]}" y1="#{params[:y1]}"
|
|
25
|
+
x2="#{params[:x2]}"
|
|
26
|
+
y2="#{params[:y2]}"
|
|
27
|
+
style="stroke:black; stroke-width:1"/>
|
|
28
|
+
LINE
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def svg_circle(params)
|
|
32
|
+
<<~CIRCLE.gsub(/\s+/, " ").strip
|
|
33
|
+
<circle cx="#{params[:cx]}"
|
|
34
|
+
cy="#{params[:cy]}"
|
|
35
|
+
r="#{params[:r]}"
|
|
36
|
+
fill="white" style="stroke:black; stroke-width:1"/>
|
|
37
|
+
CIRCLE
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def svg_ellipse(params)
|
|
41
|
+
<<~ELLIPSE.gsub(/\s+/, " ").strip
|
|
42
|
+
<ellipse cx="#{params[:cx]}"
|
|
43
|
+
cy="#{params[:cy]}"
|
|
44
|
+
rx="#{params[:rx]}"
|
|
45
|
+
ry="#{params[:ry]}"
|
|
46
|
+
style="stroke:black; stroke-width:1" fill="white"/>
|
|
47
|
+
ELLIPSE
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def svg_text(params)
|
|
51
|
+
<<~TEXT.gsub(/\s+/, " ").strip
|
|
52
|
+
<text x="#{params[:x]}"
|
|
53
|
+
y="#{params[:y]}"
|
|
54
|
+
font-family="arial" font-size="#{params[:font_size]}"
|
|
55
|
+
fill="black" style="writing-mode:
|
|
56
|
+
#{params[:orientation].to_s}">#{params[:caption]}</text>
|
|
57
|
+
TEXT
|
|
58
|
+
end
|
|
59
|
+
end
|
data/lib/utils.rb
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
require_relative 'config'
|
|
2
|
-
|
|
3
1
|
module Utils
|
|
4
2
|
def circle_rotate(center_x, center_y, r, rotation)
|
|
5
3
|
x_rotated = center_x + r * Math.cos(rotation)
|
|
@@ -7,17 +5,11 @@ module Utils
|
|
|
7
5
|
return [x_rotated, y_rotated]
|
|
8
6
|
end
|
|
9
7
|
|
|
10
|
-
def
|
|
11
|
-
|
|
12
|
-
return fingers_range / args_num.to_f if args_num == 1
|
|
13
|
-
return 0
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def draw_line(canvas, x1, y1, x2, y2)
|
|
17
|
-
canvas.line x1: x1, y1: y1, x2: x2, y2: y2, style: Config::STYLE
|
|
8
|
+
def draw_line(x1, y1, x2, y2)
|
|
9
|
+
{ line: { x1: x1, y1: y1, x2: x2, y2: y2 } }
|
|
18
10
|
end
|
|
19
11
|
|
|
20
|
-
def draw_caption(
|
|
21
|
-
|
|
12
|
+
def draw_caption(caption, x, y, font_size = 9, orientation = :lr)
|
|
13
|
+
{ text: { x: x, y: y, caption: caption, font_size: font_size, orientation: orientation } }
|
|
22
14
|
end
|
|
23
15
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dudegl
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dmitry Khramtsov
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2019-12-
|
|
12
|
+
date: 2019-12-26 00:00:00.000000000 Z
|
|
13
13
|
dependencies: []
|
|
14
14
|
description: 'Anthropomorphic UML: visualization of code and OOP concepts in a form
|
|
15
15
|
of human body.'
|
|
@@ -19,10 +19,17 @@ executables: []
|
|
|
19
19
|
extensions: []
|
|
20
20
|
extra_rdoc_files: []
|
|
21
21
|
files:
|
|
22
|
-
- lib/
|
|
22
|
+
- lib/compose/arms.rb
|
|
23
|
+
- lib/compose/body.rb
|
|
24
|
+
- lib/compose/dudes_location.rb
|
|
25
|
+
- lib/compose/legs.rb
|
|
26
|
+
- lib/compose/limbs.rb
|
|
23
27
|
- lib/config.rb
|
|
24
|
-
- lib/dude.rb
|
|
25
28
|
- lib/dudegl.rb
|
|
29
|
+
- lib/limbs/arm.rb
|
|
30
|
+
- lib/limbs/leg.rb
|
|
31
|
+
- lib/limbs/limb.rb
|
|
32
|
+
- lib/render.rb
|
|
26
33
|
- lib/utils.rb
|
|
27
34
|
homepage: https://github.com/dmikhr/DudeGL/wiki
|
|
28
35
|
licenses:
|
data/lib/arm.rb
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
require_relative 'config'
|
|
2
|
-
require_relative 'utils'
|
|
3
|
-
|
|
4
|
-
class Arm
|
|
5
|
-
include Utils
|
|
6
|
-
|
|
7
|
-
attr_reader :end_x, :end_y, :body_side
|
|
8
|
-
|
|
9
|
-
def initialize(canvas, params, x0, y0, body_side)
|
|
10
|
-
@canvas = canvas
|
|
11
|
-
@params = params
|
|
12
|
-
@x0 = x0
|
|
13
|
-
@y0 = y0
|
|
14
|
-
@end_y = y0
|
|
15
|
-
@body_side = body_side
|
|
16
|
-
|
|
17
|
-
draw_arm
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def draw_arm
|
|
21
|
-
caption = @params[:name]
|
|
22
|
-
length = @params[:length]
|
|
23
|
-
args_num = @params[:args]
|
|
24
|
-
conditions = @params[:conditions]
|
|
25
|
-
|
|
26
|
-
length <= Config::METHOD_LENGTH_OK_MAX ? arm_length = Config::ARM_LENGTH : arm_length = Config::ARM_LENGTH_LONG
|
|
27
|
-
arm_length = - arm_length if @body_side == :left
|
|
28
|
-
@end_x = @x0 + arm_length
|
|
29
|
-
|
|
30
|
-
if conditions.positive?
|
|
31
|
-
draw_conditions(conditions, arm_length, @x0, @y0, @body_side)
|
|
32
|
-
else
|
|
33
|
-
draw_line(@canvas, @x0, @y0, @x0 + arm_length, @y0)
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
draw_caption(@canvas, caption, 0.8 * (@x0 + arm_length).round, (0.95 * @y0).round)
|
|
37
|
-
draw_fingers(args_num)
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def draw_conditions(conditions, arm_length, x0, y0, body_side)
|
|
41
|
-
lines_num = conditions + 1
|
|
42
|
-
line_length = ((arm_length.abs - conditions * Config::ELLIPSE_LENGTH) / lines_num).round
|
|
43
|
-
body_side == :left ? orientation = -1 : orientation = 1
|
|
44
|
-
|
|
45
|
-
x0 = x0
|
|
46
|
-
x1 = x0 + line_length * orientation
|
|
47
|
-
|
|
48
|
-
lines_num.times do |i|
|
|
49
|
-
draw_line(@canvas, x0, y0, x1, y0)
|
|
50
|
-
|
|
51
|
-
@canvas.ellipse cx: (x1 + Config::ELLIPSE_LENGTH * orientation / 2).round,
|
|
52
|
-
cy: y0, rx: (Config::ELLIPSE_LENGTH / 2).round, ry: (Config::ELLIPSE_LENGTH / 4).round,
|
|
53
|
-
style: Config::STYLE, fill: 'white' if i < lines_num - 1
|
|
54
|
-
|
|
55
|
-
x0 = x0 + (line_length + Config::ELLIPSE_LENGTH) * orientation
|
|
56
|
-
x1 = x0 + line_length * orientation
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def draw_fingers(args_num)
|
|
61
|
-
fingers_range = Math::PI / 2.0
|
|
62
|
-
|
|
63
|
-
if body_side == :left
|
|
64
|
-
finger_angle_start = Config::FINGER_ANGLE_START
|
|
65
|
-
finger_angle_end = finger_angle_start + fingers_range
|
|
66
|
-
finger_angle_step = calc_range(fingers_range, args_num)
|
|
67
|
-
else
|
|
68
|
-
finger_angle_start = - Config::FINGER_ANGLE_START + Math::PI
|
|
69
|
-
finger_angle_end = finger_angle_start - fingers_range
|
|
70
|
-
finger_angle_step = - calc_range(fingers_range, args_num)
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
args_num.times do |i|
|
|
74
|
-
finger_end_x, finger_end_y = circle_rotate(end_x, end_y, Config::FINGER_LENGTH,
|
|
75
|
-
finger_angle_start + finger_angle_step * i)
|
|
76
|
-
|
|
77
|
-
draw_line(@canvas, end_x, end_y, finger_end_x, finger_end_y)
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
end
|
data/lib/dude.rb
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
require_relative 'utils'
|
|
2
|
-
require_relative 'config'
|
|
3
|
-
|
|
4
|
-
class Dude
|
|
5
|
-
include Utils
|
|
6
|
-
|
|
7
|
-
attr_reader :body_right_x, :body_right_top_y, :body_left_x, :body_left_top_y
|
|
8
|
-
|
|
9
|
-
def initialize(canvas, width = 400, height = 400)
|
|
10
|
-
@width = width
|
|
11
|
-
@height = height
|
|
12
|
-
@canvas = canvas
|
|
13
|
-
draw_dude
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def draw_dude
|
|
17
|
-
# head center
|
|
18
|
-
head_center_x = (0.5 * @width).round
|
|
19
|
-
head_center_y = (0.3 * @height).round
|
|
20
|
-
|
|
21
|
-
@body_right_x, @body_right_top_y = circle_rotate(head_center_x, head_center_y,
|
|
22
|
-
Config::HEAD_RADIUS,
|
|
23
|
-
Config::BODY_CENTER + Config::SLIM_FACTOR)
|
|
24
|
-
@body_left_x, @body_left_top_y = circle_rotate(head_center_x, head_center_y,
|
|
25
|
-
Config::HEAD_RADIUS,
|
|
26
|
-
Config::BODY_CENTER - Config::SLIM_FACTOR)
|
|
27
|
-
# head
|
|
28
|
-
@canvas.circle cx: head_center_x, cy: head_center_y, r: Config::HEAD_RADIUS,
|
|
29
|
-
fill: 'white', style: Config::STYLE
|
|
30
|
-
# right part of a body
|
|
31
|
-
draw_line(@canvas, @body_right_x, @body_right_top_y,
|
|
32
|
-
@body_right_x, @body_right_top_y + Config::BODY_LENGTH)
|
|
33
|
-
# left part of a body
|
|
34
|
-
draw_line(@canvas, @body_left_x, @body_left_top_y,
|
|
35
|
-
@body_left_x, @body_left_top_y + Config::BODY_LENGTH)
|
|
36
|
-
# bottom
|
|
37
|
-
draw_line(@canvas, @body_right_x, @body_right_top_y + Config::BODY_LENGTH,
|
|
38
|
-
@body_left_x, @body_left_top_y + Config::BODY_LENGTH)
|
|
39
|
-
end
|
|
40
|
-
end
|