dxf_io 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.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +224 -0
- data/Rakefile +1 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/dxf_io.gemspec +34 -0
- data/lib/dxf_io.rb +13 -0
- data/lib/dxf_io/constants.rb +24 -0
- data/lib/dxf_io/entity.rb +21 -0
- data/lib/dxf_io/entity/arc.rb +44 -0
- data/lib/dxf_io/entity/circle.rb +33 -0
- data/lib/dxf_io/entity/dimension.rb +14 -0
- data/lib/dxf_io/entity/ellipse.rb +46 -0
- data/lib/dxf_io/entity/hatch.rb +14 -0
- data/lib/dxf_io/entity/header.rb +7 -0
- data/lib/dxf_io/entity/leader.rb +14 -0
- data/lib/dxf_io/entity/line.rb +14 -0
- data/lib/dxf_io/entity/mline.rb +14 -0
- data/lib/dxf_io/entity/mtext.rb +13 -0
- data/lib/dxf_io/entity/other.rb +237 -0
- data/lib/dxf_io/entity/polyline.rb +14 -0
- data/lib/dxf_io/entity/spline.rb +13 -0
- data/lib/dxf_io/entity/support.rb +9 -0
- data/lib/dxf_io/entity/support/point.rb +114 -0
- data/lib/dxf_io/entity/text.rb +14 -0
- data/lib/dxf_io/reader.rb +139 -0
- data/lib/dxf_io/version.rb +3 -0
- data/lib/dxf_io/wrapper.rb +45 -0
- data/lib/dxf_io/writer.rb +215 -0
- metadata +122 -0
@@ -0,0 +1,33 @@
|
|
1
|
+
module DxfIO
|
2
|
+
module Entity
|
3
|
+
class Circle < Other
|
4
|
+
ADDITIONAL_GROUP_CODES = {radius: 40}.freeze
|
5
|
+
|
6
|
+
ADDITIONAL_GROUP_CODES.each_pair do |method_name, group_code|
|
7
|
+
class_eval <<-EOT, __FILE__, __LINE__ + 1
|
8
|
+
def #{method_name} # def radius
|
9
|
+
to_h[#{group_code}] # to_h[40]
|
10
|
+
end # end
|
11
|
+
EOT
|
12
|
+
end
|
13
|
+
|
14
|
+
def center
|
15
|
+
points.first
|
16
|
+
end
|
17
|
+
|
18
|
+
def bordering_points
|
19
|
+
[ center + [radius, 0],
|
20
|
+
center + [0, radius],
|
21
|
+
center - [radius, 0],
|
22
|
+
center - [0, radius] ]
|
23
|
+
end
|
24
|
+
|
25
|
+
protected
|
26
|
+
|
27
|
+
def initialize(groups, representation_hash)
|
28
|
+
@representation_hash = representation_hash
|
29
|
+
super(groups)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module DxfIO
|
2
|
+
module Entity
|
3
|
+
class Ellipse < Other
|
4
|
+
ADDITIONAL_GROUP_CODES = {minor_to_major_ration: 40}.freeze
|
5
|
+
|
6
|
+
ADDITIONAL_GROUP_CODES.each_pair do |method_name, group_code|
|
7
|
+
class_eval <<-EOT, __FILE__, __LINE__ + 1
|
8
|
+
def #{method_name} # def radius
|
9
|
+
to_h[#{group_code}] # to_h[40]
|
10
|
+
end # end
|
11
|
+
EOT
|
12
|
+
end
|
13
|
+
|
14
|
+
def center
|
15
|
+
points.find(&:start?)
|
16
|
+
end
|
17
|
+
|
18
|
+
def major_axis_endpoint_vector
|
19
|
+
points.find(&:end?)
|
20
|
+
end
|
21
|
+
|
22
|
+
def minor_axis_endpoint_vector
|
23
|
+
major_axis_endpoint_vector.rotate_90 * minor_to_major_ration
|
24
|
+
end
|
25
|
+
|
26
|
+
def major_axis_points
|
27
|
+
[center + major_axis_endpoint_vector, center + major_axis_endpoint_vector.rotate_180]
|
28
|
+
end
|
29
|
+
|
30
|
+
def minor_axis_points
|
31
|
+
[center + minor_axis_endpoint_vector, center + minor_axis_endpoint_vector.rotate_180]
|
32
|
+
end
|
33
|
+
|
34
|
+
def bordering_points
|
35
|
+
major_axis_points + minor_axis_points
|
36
|
+
end
|
37
|
+
|
38
|
+
protected
|
39
|
+
|
40
|
+
def initialize(groups, representation_hash)
|
41
|
+
@representation_hash = representation_hash
|
42
|
+
super(groups)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,237 @@
|
|
1
|
+
module DxfIO
|
2
|
+
module Entity
|
3
|
+
class Other
|
4
|
+
|
5
|
+
# start point:
|
6
|
+
# x coordinate - 10
|
7
|
+
# y coordinate - 20
|
8
|
+
# end point:
|
9
|
+
# x coordinate - 11
|
10
|
+
# y coordinate - 21
|
11
|
+
START_POINT_GROUP_NUMS = DxfIO::Constants::START_POINT_GROUP_NUMS
|
12
|
+
END_POINT_GROUP_NUMS = DxfIO::Constants::END_POINT_GROUP_NUMS
|
13
|
+
X_COORDINATE_GROUP_NUMS = [10, 11].freeze
|
14
|
+
Y_COORDINATE_GROUP_NUMS = [20, 21].freeze
|
15
|
+
Z_COORDINATE_GROUP_NUMS = [30, 31].freeze
|
16
|
+
|
17
|
+
TYPE_NAME_VALUE_MAPPING = DxfIO::Constants::ENTITIES_TYPE_NAME_VALUE_MAPPING
|
18
|
+
|
19
|
+
GROUP_CODES = {type: 0}.freeze
|
20
|
+
|
21
|
+
def initialize(groups)
|
22
|
+
if groups.is_a? Array
|
23
|
+
@groups = groups
|
24
|
+
else
|
25
|
+
raise ArgumentError, 'groups must be an Array'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_h
|
30
|
+
@representation_hash ||=
|
31
|
+
@groups.inject({}) do |h, group|
|
32
|
+
group_value = group.values.first
|
33
|
+
group_values = h[group.keys.first]
|
34
|
+
if group_values.nil?
|
35
|
+
h[group.keys.first] = group_value
|
36
|
+
elsif group_values.is_a? Array
|
37
|
+
h[group.keys.first] << group_value
|
38
|
+
else
|
39
|
+
h[group.keys.first] = [group_values, group_value]
|
40
|
+
end
|
41
|
+
h
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
alias to_hash to_h
|
46
|
+
|
47
|
+
def to_a
|
48
|
+
@groups
|
49
|
+
end
|
50
|
+
|
51
|
+
GROUP_CODES.each_pair do |method_name, group_code|
|
52
|
+
class_eval <<-EOT, __FILE__, __LINE__ + 1
|
53
|
+
def #{method_name} # def type
|
54
|
+
to_h[#{group_code}] # to_h[0]
|
55
|
+
end # end
|
56
|
+
EOT
|
57
|
+
end
|
58
|
+
|
59
|
+
TYPE_NAME_VALUE_MAPPING.each_pair do |method_name, type_value|
|
60
|
+
class_eval <<-EOT, __FILE__, __LINE__ + 1
|
61
|
+
def #{method_name}? # def ellipse?
|
62
|
+
type == '#{type_value}' # type == 'ELLIPSE'
|
63
|
+
end # end
|
64
|
+
|
65
|
+
def to_#{method_name} # def to_ellise
|
66
|
+
DxfIO::Entity::#{method_name.capitalize}.new(@groups, to_h) # DxfIO::Entity::Ellipse.new(@groups, to_h)
|
67
|
+
end # end
|
68
|
+
EOT
|
69
|
+
end
|
70
|
+
|
71
|
+
def points
|
72
|
+
groups = validate_point_groups(point_groups)
|
73
|
+
groups[1..-1].each.with_index.inject([]) do |result, (group, index)|
|
74
|
+
if (index % 2) == 0
|
75
|
+
type = start_point?(group) ? :start : :end
|
76
|
+
result << DxfIO::Entity::Support::Point.new(groups[index].values.first,
|
77
|
+
group.values.first,
|
78
|
+
type: type)
|
79
|
+
else
|
80
|
+
result
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# overall dimensions functions
|
86
|
+
|
87
|
+
# redefined in subclasses
|
88
|
+
def bordering_points
|
89
|
+
points
|
90
|
+
end
|
91
|
+
|
92
|
+
def left_down_point
|
93
|
+
DxfIO::Entity::Support::Point.new(bordering_xs.min, bordering_ys.min)
|
94
|
+
end
|
95
|
+
|
96
|
+
def height
|
97
|
+
(bordering_ys.max - bordering_ys.min).abs
|
98
|
+
end
|
99
|
+
|
100
|
+
def width
|
101
|
+
(bordering_xs.max - bordering_xs.min).abs
|
102
|
+
end
|
103
|
+
|
104
|
+
# coordinates functions
|
105
|
+
|
106
|
+
def xs
|
107
|
+
points.collect(&:x)
|
108
|
+
end
|
109
|
+
|
110
|
+
def ys
|
111
|
+
points.collect(&:y)
|
112
|
+
end
|
113
|
+
|
114
|
+
def bordering_xs
|
115
|
+
bordering_points.collect(&:x)
|
116
|
+
end
|
117
|
+
|
118
|
+
def bordering_ys
|
119
|
+
bordering_points.collect(&:y)
|
120
|
+
end
|
121
|
+
|
122
|
+
# other properties functions
|
123
|
+
|
124
|
+
# is entity a rectangle figure without rotation
|
125
|
+
def frame?
|
126
|
+
if points.count < 4
|
127
|
+
false
|
128
|
+
else
|
129
|
+
((points[0].x == points[3].x) && (points[1].x == points[2].x) &&
|
130
|
+
(points[0].y == points[1].y) && (points[2].y == points[3].y)) ||
|
131
|
+
((points[0].y == points[3].y) && (points[1].y == points[2].y) &&
|
132
|
+
(points[0].x == points[1].x) && (points[2].x == points[3].x))
|
133
|
+
# Alternative checking
|
134
|
+
# points[1..-1].each.with_index.inject(true) do |result, (point, index)|
|
135
|
+
# # TODO: need additionally checking on periodical alternation and on direction (clockwise or counter-clockwise)
|
136
|
+
# result && point != points[index] && (point.x == points[index].x || point.y == points[index].y)
|
137
|
+
# end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# moving operations
|
142
|
+
|
143
|
+
# clear alternative for "+" method
|
144
|
+
# move all points of Entity on specified vector
|
145
|
+
def move_to!(point)
|
146
|
+
if point.is_a? DxfIO::Entity::Support::Point
|
147
|
+
@groups.each do |group|
|
148
|
+
if x_coordinate?(group)
|
149
|
+
group[group.keys.first] = group.values.first + point.x
|
150
|
+
elsif y_coordinate?(group)
|
151
|
+
group[group.keys.first] = group.values.first + point.y
|
152
|
+
end
|
153
|
+
end
|
154
|
+
else
|
155
|
+
raise ArgumentError, 'argument must be a DxfIO::Entity::Support::Point'
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
# math operations
|
160
|
+
|
161
|
+
# add point to each point onto current entity
|
162
|
+
# @warning operator modify current object
|
163
|
+
alias + move_to!
|
164
|
+
|
165
|
+
# @warning operator modify current object
|
166
|
+
def -(point)
|
167
|
+
if point.is_a? DxfIO::Entity::Support::Point
|
168
|
+
self + (-point)
|
169
|
+
else
|
170
|
+
raise ArgumentError, 'argument must be a DxfIO::Entity::Support::Point'
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
private
|
175
|
+
|
176
|
+
# @warning experimental method
|
177
|
+
def points=(new_points)
|
178
|
+
# firstly remove all points from group
|
179
|
+
@groups.delete_if do |group|
|
180
|
+
(X_COORDINATE_GROUP_NUMS +
|
181
|
+
Y_COORDINATE_GROUP_NUMS +
|
182
|
+
Z_COORDINATE_GROUP_NUMS).include? group.keys.first
|
183
|
+
end
|
184
|
+
# secondary insert new points into @groups
|
185
|
+
@groups += new_points.collect(&:to_dxf_array)
|
186
|
+
end
|
187
|
+
|
188
|
+
# checking types of coordinate
|
189
|
+
|
190
|
+
def start_point?(group)
|
191
|
+
START_POINT_GROUP_NUMS.include? group.keys.first
|
192
|
+
end
|
193
|
+
|
194
|
+
def end_point?(group)
|
195
|
+
END_POINT_GROUP_NUMS.include? group.keys.first
|
196
|
+
end
|
197
|
+
|
198
|
+
def x_coordinate?(group)
|
199
|
+
X_COORDINATE_GROUP_NUMS.include? group.keys.first
|
200
|
+
end
|
201
|
+
|
202
|
+
def y_coordinate?(group)
|
203
|
+
Y_COORDINATE_GROUP_NUMS.include? group.keys.first
|
204
|
+
end
|
205
|
+
|
206
|
+
# points selection
|
207
|
+
|
208
|
+
def point_groups
|
209
|
+
@groups.inject([]) do |h, group|
|
210
|
+
if x_coordinate?(group) || y_coordinate?(group)
|
211
|
+
h << group
|
212
|
+
else
|
213
|
+
h
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
# reject invalid sequences of coordinate groups
|
219
|
+
def validate_point_groups(groups)
|
220
|
+
groups[1..-1].each.with_index.inject([]) do |result, (group, index)|
|
221
|
+
if y_coordinate?(group)
|
222
|
+
if x_coordinate?(groups[index]) &&
|
223
|
+
( (start_point?(group) && start_point?(groups[index])) ||
|
224
|
+
(end_point?(group) && end_point?(groups[index]))
|
225
|
+
)
|
226
|
+
result << groups[index]
|
227
|
+
result << group
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
result
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|