autocad 0.4.6 → 0.5

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 (83) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop/minitest.yml +2 -2
  3. data/.rubocop/strict.yml +4 -4
  4. data/.rubocop.yml +36 -33
  5. data/CHANGELOG.md +5 -5
  6. data/LICENSE.txt +21 -21
  7. data/README.md +134 -39
  8. data/Rakefile +26 -10
  9. data/exe/autocad +3 -3
  10. data/gemfiles/rubocop.gemfile +2 -1
  11. data/lib/autocad/app.rb +127 -28
  12. data/lib/autocad/arc.rb +3 -0
  13. data/lib/autocad/block.rb +11 -6
  14. data/lib/autocad/block_reference.rb +33 -4
  15. data/lib/autocad/bounding_box.rb +202 -0
  16. data/lib/autocad/dim_style.rb +4 -0
  17. data/lib/autocad/drawing.rb +873 -172
  18. data/lib/autocad/element.rb +217 -25
  19. data/lib/autocad/errors.rb +9 -0
  20. data/lib/autocad/filter.rb +502 -168
  21. data/lib/autocad/layer.rb +129 -41
  22. data/lib/autocad/layout.rb +120 -0
  23. data/lib/autocad/line.rb +154 -55
  24. data/lib/autocad/message_box.rb +95 -95
  25. data/lib/autocad/model.rb +217 -89
  26. data/lib/autocad/mtext.rb +189 -110
  27. data/lib/autocad/plot.rb +45 -0
  28. data/lib/autocad/plot_configuration.rb +372 -0
  29. data/lib/autocad/point.rb +7 -0
  30. data/lib/autocad/point3d.rb +18 -11
  31. data/lib/autocad/pviewport.rb +136 -21
  32. data/lib/autocad/selection_filter.rb +358 -180
  33. data/lib/autocad/selection_set.rb +140 -61
  34. data/lib/autocad/selection_set_adapter.rb +187 -8
  35. data/lib/autocad/spline.rb +27 -0
  36. data/lib/autocad/text.rb +66 -11
  37. data/lib/autocad/text_style.rb +4 -0
  38. data/lib/autocad/version.rb +1 -1
  39. data/lib/autocad/viewport.rb +57 -0
  40. data/lib/autocad.rb +126 -30
  41. data/lib/faa/cleanup.rb +137 -0
  42. data/lib/win32ole_helper.rb +52 -0
  43. data/rbs_collection.lock.yaml +38 -18
  44. data/sig/generated/autocad/app.rbs +278 -251
  45. data/sig/generated/autocad/arc.rbs +6 -3
  46. data/sig/generated/autocad/block.rbs +8 -5
  47. data/sig/generated/autocad/block_reference.rbs +99 -59
  48. data/sig/generated/autocad/bounding_box.rbs +78 -0
  49. data/sig/generated/autocad/dim_style.rbs +6 -0
  50. data/sig/generated/autocad/drawing.rbs +597 -158
  51. data/sig/generated/autocad/element.rbs +233 -166
  52. data/sig/generated/autocad/errors.rbs +29 -23
  53. data/sig/generated/autocad/filter.rbs +388 -60
  54. data/sig/generated/autocad/layer.rbs +76 -19
  55. data/sig/generated/autocad/layout.rbs +64 -0
  56. data/sig/generated/autocad/line.rbs +128 -25
  57. data/sig/generated/autocad/message_box.rbs +81 -81
  58. data/sig/generated/autocad/model.rbs +115 -41
  59. data/sig/generated/autocad/mtext.rbs +123 -0
  60. data/sig/generated/autocad/plot.rbs +26 -0
  61. data/sig/generated/autocad/plot_configuration.rbs +176 -0
  62. data/sig/generated/autocad/point.rbs +7 -0
  63. data/sig/generated/autocad/point3d.rbs +70 -66
  64. data/sig/generated/autocad/pviewport.rbs +64 -0
  65. data/sig/generated/autocad/selection_filter.rbs +226 -50
  66. data/sig/generated/autocad/selection_set.rbs +112 -37
  67. data/sig/generated/autocad/selection_set_adapter.rbs +235 -28
  68. data/sig/generated/autocad/spline.rbs +22 -0
  69. data/sig/generated/autocad/text.rbs +66 -7
  70. data/sig/generated/autocad/text_style.rbs +6 -0
  71. data/sig/generated/autocad/viewport.rbs +19 -2
  72. data/sig/generated/autocad.rbs +140 -68
  73. data/sig/generated/faa/cleanup.rbs +53 -0
  74. data/sig/generated/win32ole_helper.rbs +9 -0
  75. data/sig/prototype/lib/autocad/app.rbs +3 -1
  76. data/sig/prototype/lib/autocad/bounding_box.rbs +15 -0
  77. data/sig/prototype/lib/autocad/drawing.rbs +6 -0
  78. data/sig/prototype/lib/autocad/layer.rbs +5 -0
  79. data/sig/prototype/lib/autocad/viewport.rbs +7 -0
  80. data/sig/prototype/lib/autocad.rbs +1 -1
  81. metadata +29 -5
  82. data/event_handler.log +0 -24
  83. data/sig/generated/autocad/text_node.rbs +0 -37
@@ -1,168 +1,502 @@
1
- module Autocad
2
- class Filter
3
- attr_reader :types, :values, :clauses
4
-
5
- def initialize(clauses: {})
6
- @clauses = clauses
7
- @types = []
8
- @values = []
9
- end
10
-
11
- def new_filter(clause, value)
12
- new_clauses = clauses.dup
13
- new_clauses[clause] = value
14
- Filter.new(clauses: new_clauses)
15
- end
16
-
17
- def has_filters?
18
- true
19
- end
20
-
21
- # convert the clauses to the values and types needed for autocad filter
22
- # rbs return Array[Array,Array] -- the types and values array
23
- def convert_clauses
24
- types = []
25
- values = []
26
-
27
- case clauses.keys.first
28
- when :type
29
- types << 0
30
- values << clauses[:type]
31
- when :layer
32
- types << 8
33
- values << clauses[:layer]
34
- when :color
35
- types << 62
36
- values << clauses[:color]
37
- when :block_reference
38
- types << 0
39
- values << 'INSERT'
40
- if clauses[:block_reference]
41
- types << 1
42
- values << clauses[:block_reference]
43
- end
44
- when :paper_space
45
- types << 67
46
- values << 1
47
- when :model_space
48
- types << 67
49
- values << 0
50
- when :text_content
51
- types << 1 # DXF type code 1 for text content
52
- values << clauses[:text_content]
53
- when :and, :or, :xor
54
- operator = clauses.keys.first.to_s.upcase
55
- types << -4
56
- values << "<#{operator}"
57
-
58
- clauses[clauses.keys.first].each do |condition|
59
- sub_types, sub_values = condition.convert_clauses
60
- types.concat(sub_types)
61
- values.concat(sub_values)
62
- end
63
-
64
- types << -4
65
- values << "#{operator}>"
66
- when :not
67
- types << -4
68
- values << '<NOT'
69
-
70
- sub_types, sub_values = clauses[:not].convert_clauses
71
- types.concat(sub_types)
72
- values.concat(sub_values)
73
-
74
- types << -4
75
- values << 'NOT>'
76
- when :gt
77
- types.concat([-4, 40])
78
- values.concat(['>=', clauses[:gt]])
79
- when :lt
80
- types.concat([-4, 40])
81
- values.concat(['<=', clauses[:lt]])
82
- when :eq
83
- types.concat([-4, 40])
84
- values.concat(['=', clauses[:eq]])
85
- when :neq
86
- types.concat([-4, 40])
87
- values.concat(['<>', clauses[:neq]])
88
- end
89
-
90
- [types, values]
91
- end
92
-
93
- # Logical Operators
94
- def and(*conditions)
95
- new_filter(:and, conditions)
96
- end
97
-
98
- def merge_conditions(existing, new_condition)
99
- end
100
-
101
- def or(*conditions)
102
- new_filter(:or, conditions)
103
- end
104
-
105
- def xor(condition1, condition2)
106
- new_filter(:xor, [condition1, condition2])
107
- end
108
-
109
- def not(condition)
110
- new_filter(:not, condition)
111
- end
112
-
113
- # Relational Operators
114
- # f.type("Circle").greater_than(5)
115
- def greater_than(value)
116
- new_filter(:gt, value)
117
- end
118
-
119
- def less_than(value)
120
- new_filter(:lt, value)
121
- end
122
-
123
- def equal_to(value)
124
- new_filter(:eq, value)
125
- end
126
-
127
- def not_equal_to(value)
128
- new_filter(:neq, value)
129
- end
130
-
131
- def block_reference(name = nil)
132
- new_filter(:block_reference, name)
133
- end
134
-
135
- def name(value)
136
- new_filter(:name, value)
137
- end
138
-
139
- def type(kind)
140
- new_filter(:type, kind)
141
- end
142
-
143
- def layer(name)
144
- new_filter(:layer, name)
145
- end
146
-
147
- def visible(vis = true)
148
- new_filter(:visible, vis)
149
- end
150
-
151
- def color(num)
152
- new_filter(:color, num)
153
- end
154
-
155
- def paper_space
156
- new_filter(:paper_space, nil)
157
- end
158
-
159
- def model_space
160
- new_filter(:model_space, nil)
161
- end
162
-
163
- def has_text(str)
164
- new_filter(:text_content, str)
165
- end
166
-
167
- end
168
- end
1
+ module Autocad
2
+ # Builds complex filter expressions for AutoCAD entity selection
3
+ #
4
+ # This class provides a functional, immutable approach to building
5
+ # selection filters with a fluent interface. Each method returns a new
6
+ # Filter instance with the added condition.
7
+ #
8
+ # The Filter class is the core of the selection system, providing:
9
+ # - Logical operators (AND, OR, XOR, NOT)
10
+ # - Property filters (type, layer, color, etc.)
11
+ # - Numeric comparisons (greater than, less than, etc.)
12
+ # - Special entity filters (block references, text, etc.)
13
+ #
14
+ # @example Create a filter for red circles
15
+ # filter = Filter.new
16
+ # .type("CIRCLE")
17
+ # .color(1)
18
+ #
19
+ # @example Combine filters with logical operators
20
+ # text_filter = Filter.new.type("TEXT").or.type("MTEXT")
21
+ # layer_filter = Filter.new.layer("NOTES")
22
+ # combined = Filter.new.and(text_filter, layer_filter)
23
+ #
24
+ # @example Complex filter with nested conditions
25
+ # filter = Filter.new.and(
26
+ # Filter.new.or(
27
+ # Filter.new.type("CIRCLE"),
28
+ # Filter.new.type("ARC")
29
+ # ),
30
+ # Filter.new.not(
31
+ # Filter.new.layer("HIDDEN")
32
+ # )
33
+ # )
34
+ class Filter
35
+ # @return [Array<Integer>] DXF group codes for filtering
36
+ # @return [Array<Object>] Values corresponding to types
37
+ # @return [Hash<Symbol, Object>] Internal representation of filter conditions
38
+ # @rbs attr_reader types: Array[Integer] -- DXF group codes for filtering
39
+ # @rbs attr_reader values: Array[untyped] -- Values corresponding to types
40
+ # @rbs attr_reader clauses: Hash[Symbol, untyped] -- Internal representation of filter conditions
41
+ attr_reader :types, :values, :clauses
42
+
43
+ # Initialize a new filter with optional clauses
44
+ #
45
+ # @param clauses [Hash<Symbol, Object>] Initial filter clauses
46
+ # @return [void]
47
+ # @rbs clauses: Hash[Symbol, untyped] -- Initial filter clauses
48
+ # @rbs return void
49
+ def initialize(clauses: {})
50
+ @clauses = clauses
51
+ @types = []
52
+ @values = []
53
+ end
54
+
55
+ # Create a new filter with an additional clause
56
+ #
57
+ # This method implements the immutable pattern - instead of modifying
58
+ # the current filter, it returns a new filter with the added clause.
59
+ #
60
+ # @param clause [Symbol] The clause type
61
+ # @param value [Object] The clause value
62
+ # @return [Filter] A new filter instance
63
+ # @rbs clause: Symbol -- The clause type
64
+ # @rbs value: untyped -- The clause value
65
+ # @rbs return Filter -- A new filter instance
66
+ def new_filter(clause, value)
67
+ new_clauses = clauses.dup
68
+ new_clauses[clause] = value
69
+ Filter.new(clauses: new_clauses)
70
+ end
71
+
72
+ # Check if filter has any conditions
73
+ #
74
+ # @return [Boolean] True if the filter has conditions
75
+ # @note This implementation always returns true and should be fixed
76
+ # to check if clauses.any? instead
77
+ # @rbs return bool -- Always returns true (should check clauses.any?)
78
+ def has_filters?
79
+ true
80
+ end
81
+
82
+ # Convert the clauses to AutoCAD selection filter format
83
+ #
84
+ # Transforms the internal filter representation into the format
85
+ # expected by AutoCAD's selection API: arrays of group codes and values.
86
+ #
87
+ # @return [Array<Array<Integer>, Array<Object>>] The types and values arrays
88
+ # @rbs return [Array[Integer], Array[untyped]] -- The types and values arrays
89
+ def convert_clauses
90
+ types = []
91
+ values = []
92
+
93
+ case clauses.keys.first
94
+ when :type
95
+ # Entity type filter (e.g., LINE, CIRCLE)
96
+ types << 0 # DXF group code for entity type
97
+ values << clauses[:type]
98
+ when :layer
99
+ # Layer filter
100
+ types << 8 # DXF group code for layer
101
+ values << clauses[:layer]
102
+ when :color
103
+ # Color filter
104
+ types << 62 # DXF group code for color
105
+ values << clauses[:color]
106
+ when :block_reference
107
+ # Block reference filter
108
+ types << 0 # Entity type
109
+ values << "INSERT" # Block reference entity type
110
+ if clauses[:block_reference]
111
+ types << 2 # Block name
112
+ values << clauses[:block_reference]
113
+ end
114
+ when :paper_space
115
+ # Paper space filter
116
+ types << 67 # Space indicator
117
+ values << 1 # 1 = paper space
118
+ when :model_space
119
+ # Model space filter
120
+ types << 67 # Space indicator
121
+ values << 0 # 0 = model space
122
+ when :text_content
123
+ # Text content filter
124
+ types << 1 # DXF group code for text content
125
+ values << clauses[:text_content]
126
+ when :and, :or, :xor
127
+ # Logical operators use special syntax with angle brackets
128
+ operator = clauses.keys.first.to_s.upcase
129
+ types << -4 # DXF group code for extended data
130
+ values << "<#{operator}" # Start logical group
131
+
132
+ clauses[clauses.keys.first].each do |condition|
133
+ sub_types, sub_values = condition.convert_clauses
134
+ types.concat(sub_types)
135
+ values.concat(sub_values)
136
+ end
137
+
138
+ types << -4 # Close logical group
139
+ values << "#{operator}>"
140
+ when :not
141
+ # Logical NOT operator
142
+ types << -4
143
+ values << "<NOT"
144
+
145
+ sub_types, sub_values = clauses[:not].convert_clauses
146
+ types.concat(sub_types)
147
+ values.concat(sub_values)
148
+
149
+ types << -4
150
+ values << "NOT>"
151
+ when :gt
152
+ # Greater than comparison
153
+ types.concat([-4, 40]) # -4 = operator, 40 = floating point value
154
+ values.concat([">=", clauses[:gt]])
155
+ when :lt
156
+ # Less than comparison
157
+ types.concat([-4, 40])
158
+ values.concat(["<=", clauses[:lt]])
159
+ when :eq
160
+ # Equal to comparison
161
+ types.concat([-4, 40])
162
+ values.concat(["=", clauses[:eq]])
163
+ when :neq
164
+ # Not equal to comparison
165
+ types.concat([-4, 40])
166
+ values.concat(["<>", clauses[:neq]])
167
+ end
168
+
169
+ [types, values]
170
+ end
171
+
172
+ # Logical AND combination of filters
173
+ #
174
+ # Creates a new filter that combines multiple conditions with AND logic.
175
+ # All conditions must be met for an entity to be selected.
176
+ #
177
+ # @param conditions [Array<Filter>] Filters to combine
178
+ # @return [Filter] A new filter with AND condition
179
+ # @example Combine type and layer filters
180
+ # f.and(f.type("CIRCLE"), f.layer("WALLS"))
181
+ # @example Complex nested AND condition
182
+ # f.and(
183
+ # f.layer("ELECTRICAL"),
184
+ # f.or(f.type("LINE"), f.type("POLYLINE"))
185
+ # )
186
+ # @rbs *conditions: Array[Filter] -- Filters to combine
187
+ # @rbs return Filter -- A new filter with AND condition
188
+ def and(*conditions)
189
+ new_filter(:and, conditions)
190
+ end
191
+
192
+ # Placeholder for merging conditions (unimplemented)
193
+ #
194
+ # @note This method is a placeholder and not currently implemented
195
+ # @param existing [Filter] Existing filter
196
+ # @param new_condition [Filter] New filter to merge
197
+ # @return [void]
198
+ # @rbs existing: Filter -- Existing filter
199
+ # @rbs new_condition: Filter -- New filter to merge
200
+ # @rbs return void
201
+ def merge_conditions(existing, new_condition)
202
+ # Implementation pending
203
+ end
204
+
205
+ # Logical OR combination of filters
206
+ #
207
+ # Creates a new filter that combines multiple conditions with OR logic.
208
+ # Any condition can be met for an entity to be selected.
209
+ #
210
+ # @param conditions [Array<Filter>] Filters to combine
211
+ # @return [Filter] A new filter with OR condition
212
+ # @example Select circles or arcs
213
+ # f.or(f.type("CIRCLE"), f.type("ARC"))
214
+ # @example Select entities on multiple layers
215
+ # f.or(f.layer("WALLS"), f.layer("DOORS"), f.layer("WINDOWS"))
216
+ # @rbs *conditions: Array[Filter] -- Filters to combine
217
+ # @rbs return Filter -- A new filter with OR condition
218
+ def or(*conditions)
219
+ new_filter(:or, conditions)
220
+ end
221
+
222
+ # Logical XOR combination of two filters
223
+ #
224
+ # Creates a new filter that combines two conditions with XOR logic.
225
+ # Exactly one condition must be met for an entity to be selected.
226
+ #
227
+ # @param condition1 [Filter] First filter
228
+ # @param condition2 [Filter] Second filter
229
+ # @return [Filter] A new filter with XOR condition
230
+ # @example Select circles or red entities, but not red circles
231
+ # f.xor(f.type("CIRCLE"), f.color(1))
232
+ # @rbs condition1: Filter -- First filter
233
+ # @rbs condition2: Filter -- Second filter
234
+ # @rbs return Filter -- A new filter with XOR condition
235
+ def xor(condition1, condition2)
236
+ new_filter(:xor, [condition1, condition2])
237
+ end
238
+
239
+ # Logical NOT of a filter
240
+ #
241
+ # Creates a new filter that negates a condition.
242
+ # Entities that do NOT meet the condition will be selected.
243
+ #
244
+ # @param condition [Filter] Filter to negate
245
+ # @return [Filter] A new filter with NOT condition
246
+ # @example Select all entities except circles
247
+ # f.not(f.type("CIRCLE"))
248
+ # @example Select entities not on the HIDDEN layer
249
+ # f.not(f.layer("HIDDEN"))
250
+ # @rbs condition: Filter -- Filter to negate
251
+ # @rbs return Filter -- A new filter with NOT condition
252
+ def not(condition)
253
+ new_filter(:not, condition)
254
+ end
255
+
256
+ # Filter for values greater than specified value
257
+ #
258
+ # Creates a new filter for numeric comparisons.
259
+ # Typically used for radius, length, or other dimensional properties.
260
+ #
261
+ # @param value [Numeric] Value to compare against
262
+ # @return [Filter] A new filter with greater than condition
263
+ # @example Filter for circles with radius > 5
264
+ # f.type("CIRCLE").greater_than(5)
265
+ # @example Filter for lines longer than 10 units
266
+ # f.type("LINE").greater_than(10)
267
+ # @rbs value: Numeric -- Value to compare against
268
+ # @rbs return Filter -- A new filter with greater than condition
269
+ def greater_than(value)
270
+ new_filter(:gt, value)
271
+ end
272
+
273
+ # Filter for values less than specified value
274
+ #
275
+ # Creates a new filter for numeric comparisons.
276
+ # Typically used for radius, length, or other dimensional properties.
277
+ #
278
+ # @param value [Numeric] Value to compare against
279
+ # @return [Filter] A new filter with less than condition
280
+ # @example Filter for circles with radius < 10
281
+ # f.type("CIRCLE").less_than(10)
282
+ # @example Filter for text with height < 2.5
283
+ # f.type("TEXT").less_than(2.5)
284
+ # @rbs value: Numeric -- Value to compare against
285
+ # @rbs return Filter -- A new filter with less than condition
286
+ def less_than(value)
287
+ new_filter(:lt, value)
288
+ end
289
+
290
+ # Filter for values equal to specified value
291
+ #
292
+ # Creates a new filter for exact numeric matches.
293
+ # Useful for standardized dimensions or properties.
294
+ #
295
+ # @param value [Numeric] Value to compare against
296
+ # @return [Filter] A new filter with equal to condition
297
+ # @example Filter for circles with radius = 7.5
298
+ # f.type("CIRCLE").equal_to(7.5)
299
+ # @example Filter for text with exact height
300
+ # f.type("TEXT").equal_to(3.0)
301
+ # @rbs value: Numeric -- Value to compare against
302
+ # @rbs return Filter -- A new filter with equal to condition
303
+ def equal_to(value)
304
+ new_filter(:eq, value)
305
+ end
306
+
307
+ # Filter for values not equal to specified value
308
+ #
309
+ # Creates a new filter that excludes entities with specific values.
310
+ #
311
+ # @param value [Numeric] Value to compare against
312
+ # @return [Filter] A new filter with not equal to condition
313
+ # @example Filter for circles with radius != 0
314
+ # f.type("CIRCLE").not_equal_to(0)
315
+ # @example Filter for non-standard text heights
316
+ # f.type("TEXT").not_equal_to(2.5)
317
+ # @rbs value: Numeric -- Value to compare against
318
+ # @rbs return Filter -- A new filter with not equal to condition
319
+ def not_equal_to(value)
320
+ new_filter(:neq, value)
321
+ end
322
+
323
+ # Filter for block references (optionally with specific name)
324
+ #
325
+ # Creates a new filter for block reference entities.
326
+ # Optionally filters for a specific block name pattern.
327
+ #
328
+ # @param name [String, nil] Block name pattern (e.g., "DOOR*")
329
+ # @return [Filter] A new filter for block references
330
+ # @example Filter for any block reference
331
+ # f.block_reference
332
+ # @example Filter for door block references
333
+ # f.block_reference("DOOR*")
334
+ # @example Filter for furniture with specific naming pattern
335
+ # f.block_reference("FURN_*_CHAIR")
336
+ # @rbs name: String? -- Block name pattern (e.g., "DOOR*")
337
+ # @rbs return Filter -- A new filter for block references
338
+ def block_reference(name = nil)
339
+ new_filter(:block_reference, name)
340
+ end
341
+
342
+ # Filter by entity name
343
+ #
344
+ # Creates a new filter for entities with specific names.
345
+ # Useful for named objects like blocks, layers, etc.
346
+ #
347
+ # @param value [String] Entity name
348
+ # @return [Filter] A new filter for entity name
349
+ # @example Filter by specific entity name
350
+ # f.name("A123")
351
+ # @example Filter by name pattern
352
+ # f.name("DOOR_*")
353
+ # @rbs value: String -- Entity name
354
+ # @rbs return Filter -- A new filter for entity name
355
+ def name(value)
356
+ new_filter(:name, value)
357
+ end
358
+
359
+ # Filter by entity type
360
+ #
361
+ # Creates a new filter for entities of a specific type.
362
+ # This is one of the most common filters.
363
+ #
364
+ # @param kind [String] AutoCAD entity type (e.g., "LINE", "CIRCLE")
365
+ # @return [Filter] A new filter for entity type
366
+ # @example Filter for lines
367
+ # f.type("LINE")
368
+ # @example Filter for circles
369
+ # f.type("CIRCLE")
370
+ # @example Filter for multi-line text
371
+ # f.type("MTEXT")
372
+ # @rbs kind: String -- AutoCAD entity type (e.g., "LINE", "CIRCLE")
373
+ # @rbs return Filter -- A new filter for entity type
374
+ def type(kind)
375
+ new_filter(:type, kind)
376
+ end
377
+
378
+ # Filter by layer name
379
+ #
380
+ # Creates a new filter for entities on a specific layer.
381
+ # Supports exact layer names or wildcard patterns.
382
+ #
383
+ # @param name [String] Layer name
384
+ # @return [Filter] A new filter for layer
385
+ # @example Filter for entities on WALLS layer
386
+ # f.layer("WALLS")
387
+ # @example Filter for entities on any layer starting with "A-"
388
+ # f.layer("A-*")
389
+ # @rbs name: String -- Layer name
390
+ # @rbs return Filter -- A new filter for layer
391
+ def layer(name)
392
+ new_filter(:layer, name)
393
+ end
394
+
395
+ # Filter by visibility
396
+ #
397
+ # Creates a new filter for entity visibility.
398
+ # By default, filters for visible entities.
399
+ #
400
+ # @param vis [Boolean] True for visible, false for invisible
401
+ # @return [Filter] A new filter for visibility
402
+ # @example Filter for visible entities
403
+ # f.visible(true)
404
+ # @example Filter for hidden entities
405
+ # f.visible(false)
406
+ # @rbs vis: bool -- True for visible, false for invisible
407
+ # @rbs return Filter -- A new filter for visibility
408
+ def visible(vis = true)
409
+ new_filter(:visible, vis)
410
+ end
411
+
412
+ # Filter by color index
413
+ #
414
+ # Creates a new filter for entities with a specific color.
415
+ # Accepts color index (1-255) or symbolic color names.
416
+ #
417
+ # @param num [Integer] AutoCAD color index (0-255)
418
+ # @return [Filter] A new filter for color
419
+ # @example Filter for red entities
420
+ # f.color(1) # Red
421
+ # @example Filter for blue entities
422
+ # f.color(5) # Blue
423
+ # @example Filter for entities with specific color
424
+ # f.color(Autocad::Color::Green)
425
+ # @rbs num: Integer -- AutoCAD color index (0-255)
426
+ # @rbs return Filter -- A new filter for color
427
+ def color(num)
428
+ color_index = num.is_a?(Integer) ? num : Autocad.color_to_index(num)
429
+ new_filter(:color, color_index)
430
+ end
431
+
432
+ # Filter for paper space entities
433
+ #
434
+ # Creates a new filter for entities in paper space (layouts).
435
+ #
436
+ # @return [Filter] A new filter for paper space
437
+ # @example Filter for paper space entities
438
+ # f.paper_space
439
+ # @example Filter for title blocks in paper space
440
+ # f.and(f.paper_space, f.block_reference("TITLE*"))
441
+ # @rbs return Filter -- A new filter for paper space
442
+ def paper_space
443
+ new_filter(:paper_space, nil)
444
+ end
445
+
446
+ # Filter for model space entities
447
+ #
448
+ # Creates a new filter for entities in model space.
449
+ #
450
+ # @return [Filter] A new filter for model space
451
+ # @example Filter for model space entities
452
+ # f.model_space
453
+ # @example Filter for circles in model space
454
+ # f.and(f.model_space, f.type("CIRCLE"))
455
+ # @rbs return Filter -- A new filter for model space
456
+ def model_space
457
+ new_filter(:model_space, nil)
458
+ end
459
+
460
+ # Filter for text containing a string pattern
461
+ #
462
+ # Creates a new filter for text entities containing specific content.
463
+ # Works with both TEXT and MTEXT entities.
464
+ #
465
+ # @param str [String] Text pattern to search for
466
+ # @return [Filter] A new filter for text content
467
+ # @example Filter for text containing "REVISION"
468
+ # f.has_text("REVISION")
469
+ # @example Filter for text containing a specific pattern
470
+ # f.has_text("*REV*")
471
+ # @rbs str: String -- Text pattern to search for
472
+ # @rbs return Filter -- A new filter for text content
473
+ def has_text(str)
474
+ new_filter(:text_content, str)
475
+ end
476
+
477
+ # Filter for any text entity
478
+ #
479
+ # Creates a new filter for any text entity (TEXT or MTEXT).
480
+ #
481
+ # @return [Filter] A new filter for text entities
482
+ # @example Filter for any text entity
483
+ # f.text
484
+ # @example Filter for text on a specific layer
485
+ # f.and(f.text, f.layer("NOTES"))
486
+ def text
487
+ or(type("TEXT"), type("MTEXT"))
488
+ end
489
+
490
+ # Filter for entities with specific linetype
491
+ #
492
+ # Creates a new filter for entities with a specific linetype.
493
+ #
494
+ # @param name [String] Linetype name
495
+ # @return [Filter] A new filter for linetype
496
+ # @example Filter for entities with DASHED linetype
497
+ # f.linetype("DASHED")
498
+ def linetype(name)
499
+ new_filter(:linetype, name)
500
+ end
501
+ end
502
+ end