dudegl 0.1.0

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.
Files changed (5) hide show
  1. checksums.yaml +7 -0
  2. data/lib/config.rb +4 -0
  3. data/lib/dudegl.rb +154 -0
  4. data/lib/utils.rb +23 -0
  5. metadata +48 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: c04d0cd5702b11e8381dbc79bbdc7ff3de2342cf90949588938c3a2d0596f183
4
+ data.tar.gz: 78bf8825a9325dba3058cae821deed12182b1412413beb966eaa2c510f32b4f8
5
+ SHA512:
6
+ metadata.gz: b0d2a81573a6e29ed3b0b1d39b1f92b1c2a1a8cbb87662822f9416e51833f8fa39950586d92b53e36371241ecfd6206b02c3a9bf293870b659eb19cf4a9a7134
7
+ data.tar.gz: 48edbacecbc05fbc3d5aeea47a0c0458b4a4e18bc26ec5c427d8a145db1ce019ca2956988a35f28a4d8bd0696f7909de04d4057dcd44cbea4d50f410da17680a
data/lib/config.rb ADDED
@@ -0,0 +1,4 @@
1
+ module Config
2
+ STYLE = { stroke: 'black', stroke_width: 1 }
3
+ IMAGE_DIR = 'images'
4
+ end
data/lib/dudegl.rb ADDED
@@ -0,0 +1,154 @@
1
+ require 'victor'
2
+ require 'byebug'
3
+ require_relative 'config'
4
+ require_relative 'utils'
5
+
6
+ class DudeGl
7
+ include Utils
8
+
9
+ BODY_LENGTH = 140
10
+ BODY_CENTER = Math::PI * (3 / 2.0)
11
+ # defines how slim is a body
12
+ SLIM_FACTOR = Math::PI * (2 / 8.0)
13
+ HEAD_RADIUS = 40
14
+
15
+ METHOD_LENGTH_OK_MAX = 5
16
+ ARM_LENGTH = 40
17
+ ARM_LENGTH_LONG = 70
18
+ ELLIPSE_LENGTH = 10
19
+
20
+ FINGER_LENGTH = 10
21
+ FINGER_ANGLE_START = Math::PI * (3 / 4.0)
22
+
23
+ def initialize(object, width = 400, height = 400)
24
+ @object = object
25
+ @width = width
26
+ @height = height
27
+ create_canvas
28
+ draw_dude
29
+ draw_arms
30
+ end
31
+
32
+ def save_to_svg(file_name)
33
+ @canvas.save "#{Config::IMAGE_DIR}/#{file_name}"
34
+ end
35
+
36
+ private
37
+
38
+ def create_canvas
39
+ @canvas = Victor::SVG.new width: @width, height: @height, style: { background: 'white' }
40
+ end
41
+
42
+ def draw_dude
43
+ # head center
44
+ head_center_x = (0.5 * @width).round
45
+ head_center_y = (0.3 * @height).round
46
+
47
+ @body_right_x, @body_right_top_y = circle_rotate(head_center_x, head_center_y,
48
+ HEAD_RADIUS, BODY_CENTER + SLIM_FACTOR)
49
+ @body_left_x, @body_left_top_y = circle_rotate(head_center_x, head_center_y,
50
+ HEAD_RADIUS, BODY_CENTER - SLIM_FACTOR)
51
+ # head
52
+ @canvas.circle cx: head_center_x, cy: head_center_y, r: HEAD_RADIUS,
53
+ fill: 'white', style: Config::STYLE
54
+ # right part of a body
55
+ draw_line(@canvas, @body_right_x, @body_right_top_y,
56
+ @body_right_x, @body_right_top_y + BODY_LENGTH)
57
+ # left part of a body
58
+ draw_line(@canvas, @body_left_x, @body_left_top_y,
59
+ @body_left_x, @body_left_top_y + BODY_LENGTH)
60
+ # bottom
61
+ draw_line(@canvas, @body_right_x, @body_right_top_y + BODY_LENGTH,
62
+ @body_left_x, @body_left_top_y + BODY_LENGTH)
63
+ end
64
+
65
+ def draw_arm(side_arms, x0, y0, body_side)
66
+ method_name = side_arms[:name]
67
+ length = side_arms[:length]
68
+ args_num = side_arms[:args]
69
+ conditions = side_arms[:conditions]
70
+
71
+ length <= METHOD_LENGTH_OK_MAX ? arm_length = ARM_LENGTH : arm_length = ARM_LENGTH_LONG
72
+ arm_length = - arm_length if body_side == :left
73
+
74
+ if conditions.positive?
75
+ draw_conditions(conditions, arm_length, x0, y0, body_side)
76
+ else
77
+ draw_line(@canvas, x0, y0, x0 + arm_length, y0)
78
+ end
79
+
80
+ draw_caption(@canvas, method_name, 0.8 * (x0 + arm_length).round, (0.95 * y0).round)
81
+ draw_fingers(args_num, x0 + arm_length, y0, body_side)
82
+ end
83
+
84
+ def draw_arms
85
+ arms_draw_parameters
86
+ divide_arms
87
+
88
+ @left_arms_num.times do |i|
89
+ hy = (1.05 * @body_left_top_y + i * @arms_step).round
90
+ draw_arm(@left_arms[i], @body_left_x, hy, :left)
91
+ end
92
+
93
+ @right_arms_num.times do |i|
94
+ hy = (1.05 * @body_right_top_y + i * @arms_step).round
95
+ draw_arm(@right_arms[i], @body_right_x, hy, :right)
96
+ end
97
+ end
98
+
99
+ def draw_conditions(conditions, arm_length, x0, y0, body_side)
100
+ lines_num = conditions + 1
101
+ line_length = ((arm_length.abs - conditions * ELLIPSE_LENGTH) / lines_num).round
102
+ body_side == :left ? orientation = -1 : orientation = 1
103
+
104
+ x0 = x0
105
+ x1 = x0 + line_length * orientation
106
+
107
+ lines_num.times do |i|
108
+ draw_line(@canvas, x0, y0, x1, y0)
109
+
110
+ @canvas.ellipse cx: (x1 + ELLIPSE_LENGTH * orientation / 2).round,
111
+ cy: y0, rx: (ELLIPSE_LENGTH / 2).round, ry: (ELLIPSE_LENGTH / 4).round,
112
+ style: Config::STYLE, fill: 'white' if i < lines_num - 1
113
+
114
+ x0 = x0 + (line_length + ELLIPSE_LENGTH) * orientation
115
+ x1 = x0 + line_length * orientation
116
+ end
117
+ end
118
+
119
+ def arms_draw_parameters
120
+ @methods_num = @object[:methods].size
121
+ remainder = @methods_num % 2
122
+
123
+ @left_arms_num = (@methods_num - remainder) / 2 + remainder
124
+ @right_arms_num = @methods_num - @left_arms_num
125
+
126
+ # BODY_LENGTH * 0.9 - to avoid drawing hands on a body edges
127
+ @arms_step = ((BODY_LENGTH * 0.9) / @left_arms_num).round
128
+ end
129
+
130
+ def divide_arms
131
+ @left_arms = @object[:methods][0, @left_arms_num]
132
+ @right_arms = @object[:methods][@left_arms_num, @methods_num]
133
+ end
134
+
135
+ def draw_fingers(args_num, arm_end_x, arm_end_y, body_side)
136
+ fingers_range = Math::PI / 2.0
137
+
138
+ if body_side == :left
139
+ finger_angle_start = FINGER_ANGLE_START
140
+ finger_angle_end = finger_angle_start + fingers_range
141
+ finger_angle_step = calc_range(fingers_range, args_num)
142
+ else
143
+ finger_angle_start = - FINGER_ANGLE_START + Math::PI
144
+ finger_angle_end = finger_angle_start - fingers_range
145
+ finger_angle_step = - calc_range(fingers_range, args_num)
146
+ end
147
+
148
+ args_num.times do |i|
149
+ finger_end_x, finger_end_y = circle_rotate(arm_end_x, arm_end_y, FINGER_LENGTH,
150
+ finger_angle_start + finger_angle_step * i)
151
+ draw_line(@canvas, arm_end_x, arm_end_y, finger_end_x, finger_end_y)
152
+ end
153
+ end
154
+ end
data/lib/utils.rb ADDED
@@ -0,0 +1,23 @@
1
+ require_relative 'config'
2
+
3
+ module Utils
4
+ def circle_rotate(center_x, center_y, r, rotation)
5
+ x_rotated = center_x + r * Math.cos(rotation)
6
+ y_rotated = center_y - r * Math.sin(rotation)
7
+ return [x_rotated, y_rotated]
8
+ end
9
+
10
+ def calc_range(fingers_range, args_num)
11
+ return fingers_range / (args_num - 1).to_f if args_num > 1
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
18
+ end
19
+
20
+ def draw_caption(canvas, caption, x, y)
21
+ canvas.text caption, x: x, y: y, font_family: 'arial', font_size: 9, fill: 'black'
22
+ end
23
+ end
metadata ADDED
@@ -0,0 +1,48 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dudegl
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Dmitry Khramtsov
8
+ - Ivan Nemytchenko
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2019-12-11 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: 'Anthropomorphic UML: visualization of code and OOP concepts in a form
15
+ of human body.'
16
+ email:
17
+ - dp@khramtsov.net
18
+ executables: []
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - lib/config.rb
23
+ - lib/dudegl.rb
24
+ - lib/utils.rb
25
+ homepage: https://github.com/dmikhr/DudeGL/wiki
26
+ licenses:
27
+ - MIT
28
+ metadata: {}
29
+ post_install_message:
30
+ rdoc_options: []
31
+ require_paths:
32
+ - lib
33
+ required_ruby_version: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ">="
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ required_rubygems_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ requirements: []
44
+ rubygems_version: 3.0.3
45
+ signing_key:
46
+ specification_version: 4
47
+ summary: Visualization of code and OOP concepts in a form of human body
48
+ test_files: []