autocad 0.4.6

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 (89) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop/minitest.yml +2 -0
  3. data/.rubocop/strict.yml +4 -0
  4. data/.rubocop.yml +33 -0
  5. data/.solargraph.yml +22 -0
  6. data/.vscode/launch.json +30 -0
  7. data/CHANGELOG.md +5 -0
  8. data/CODE_OF_CONDUCT.md +132 -0
  9. data/Guardfile +66 -0
  10. data/LICENSE.txt +21 -0
  11. data/README.md +39 -0
  12. data/Rakefile +10 -0
  13. data/Steepfile +35 -0
  14. data/WASD-D-TDS-C001.dwg +0 -0
  15. data/WASD-D-TDS-C001.pdf +0 -0
  16. data/autocad.log +1 -0
  17. data/autocad_example.rb +26 -0
  18. data/event_handler.log +24 -0
  19. data/examples/example_save_pdf.rb +5 -0
  20. data/exe/autocad +3 -0
  21. data/exe/dgn2pdf +50 -0
  22. data/exe/pw_print +43 -0
  23. data/gemfiles/rubocop.gemfile +6 -0
  24. data/lib/autocad/app.rb +655 -0
  25. data/lib/autocad/arc.rb +29 -0
  26. data/lib/autocad/block.rb +141 -0
  27. data/lib/autocad/block_reference.rb +198 -0
  28. data/lib/autocad/drawing.rb +426 -0
  29. data/lib/autocad/element.rb +454 -0
  30. data/lib/autocad/enumerator.rb +24 -0
  31. data/lib/autocad/errors.rb +37 -0
  32. data/lib/autocad/event_handler.rb +30 -0
  33. data/lib/autocad/filter.rb +168 -0
  34. data/lib/autocad/layer.rb +41 -0
  35. data/lib/autocad/line.rb +55 -0
  36. data/lib/autocad/message_box.rb +95 -0
  37. data/lib/autocad/model.rb +89 -0
  38. data/lib/autocad/mtext.rb +110 -0
  39. data/lib/autocad/paths.rb +29 -0
  40. data/lib/autocad/point3d.rb +143 -0
  41. data/lib/autocad/pviewport.rb +21 -0
  42. data/lib/autocad/selection_filter.rb +180 -0
  43. data/lib/autocad/selection_set.rb +61 -0
  44. data/lib/autocad/selection_set_adapter.rb +146 -0
  45. data/lib/autocad/text.rb +74 -0
  46. data/lib/autocad/version.rb +5 -0
  47. data/lib/autocad.rb +161 -0
  48. data/olegen.rb +341 -0
  49. data/rbs_collection.lock.yaml +188 -0
  50. data/rbs_collection.yaml +19 -0
  51. data/scanner.obj +0 -0
  52. data/sig/generated/autocad/app.rbs +251 -0
  53. data/sig/generated/autocad/arc.rbs +17 -0
  54. data/sig/generated/autocad/block.rbs +63 -0
  55. data/sig/generated/autocad/block_reference.rbs +59 -0
  56. data/sig/generated/autocad/drawing.rbs +158 -0
  57. data/sig/generated/autocad/element.rbs +166 -0
  58. data/sig/generated/autocad/enumerator.rbs +15 -0
  59. data/sig/generated/autocad/errors.rbs +23 -0
  60. data/sig/generated/autocad/event_handler.rbs +14 -0
  61. data/sig/generated/autocad/filter.rbs +60 -0
  62. data/sig/generated/autocad/layer.rbs +19 -0
  63. data/sig/generated/autocad/line.rbs +25 -0
  64. data/sig/generated/autocad/message_box.rbs +81 -0
  65. data/sig/generated/autocad/model.rbs +41 -0
  66. data/sig/generated/autocad/paths.rbs +19 -0
  67. data/sig/generated/autocad/point3d.rbs +66 -0
  68. data/sig/generated/autocad/selection_filter.rbs +50 -0
  69. data/sig/generated/autocad/selection_set.rbs +37 -0
  70. data/sig/generated/autocad/selection_set_adapter.rbs +28 -0
  71. data/sig/generated/autocad/text.rbs +19 -0
  72. data/sig/generated/autocad/text_node.rbs +37 -0
  73. data/sig/generated/autocad/version.rbs +5 -0
  74. data/sig/generated/autocad/viewport.rbs +11 -0
  75. data/sig/generated/autocad.rbs +68 -0
  76. data/sig/prototype/lib/autocad/app.rbs +34 -0
  77. data/sig/prototype/lib/autocad/block.rbs +5 -0
  78. data/sig/prototype/lib/autocad/block_reference.rbs +5 -0
  79. data/sig/prototype/lib/autocad/drawing.rbs +13 -0
  80. data/sig/prototype/lib/autocad/element.rbs +9 -0
  81. data/sig/prototype/lib/autocad/enumerator.rbs +5 -0
  82. data/sig/prototype/lib/autocad/event_handler.rbs +7 -0
  83. data/sig/prototype/lib/autocad/model.rbs +5 -0
  84. data/sig/prototype/lib/autocad/paths.rbs +5 -0
  85. data/sig/prototype/lib/autocad.rbs +3 -0
  86. data/temp/autocad.dwg +0 -0
  87. data/temp/autocad.log +1 -0
  88. data/temp/event_handler.log +0 -0
  89. metadata +147 -0
@@ -0,0 +1,180 @@
1
+ module Autocad
2
+ class SelectionFilter
3
+ attr_reader :types, :values
4
+
5
+ def initialize
6
+ @types = []
7
+ @values = []
8
+ end
9
+
10
+ def has_filters?
11
+ @types.any?
12
+ end
13
+
14
+ # Logical Operators
15
+ def and(*conditions)
16
+ return self if conditions.empty?
17
+
18
+ @types << -4
19
+ @values << "<AND"
20
+
21
+ conditions.each do |condition|
22
+ @types.concat(condition.types)
23
+ @values.concat(condition.values)
24
+ end
25
+
26
+ @types << -4
27
+ @values << "AND>"
28
+
29
+ self
30
+ end
31
+
32
+ def or(*conditions)
33
+ return self if conditions.empty?
34
+
35
+ @types << -4
36
+ @values << "<OR"
37
+
38
+ conditions.each do |condition|
39
+ @types.concat(condition.types)
40
+ @values.concat(condition.values)
41
+ end
42
+
43
+ @types << -4
44
+ @values << "OR>"
45
+
46
+ self
47
+ end
48
+
49
+ def xor(condition1, condition2)
50
+ @types << -4
51
+ @values << "<XOR"
52
+
53
+ @types.concat(condition1.types)
54
+ @values.concat(condition1.values)
55
+
56
+ @types.concat(condition2.types)
57
+ @values.concat(condition2.values)
58
+
59
+ @types << -4
60
+ @values << "XOR>"
61
+
62
+ self
63
+ end
64
+
65
+ def not(condition)
66
+ @types << -4
67
+ @values << "<NOT"
68
+
69
+ @types.concat(condition.types)
70
+ @values.concat(condition.values)
71
+
72
+ @types << -4
73
+ @values << "NOT>"
74
+
75
+ self
76
+ end
77
+
78
+ # Relational Operators
79
+ # f.type("Circle").greater_than(5)
80
+ def greater_than(value)
81
+ @types << -4
82
+ @values << ">="
83
+ @types << 40 # floating point
84
+ @values << value
85
+ self
86
+ end
87
+
88
+ def less_than(value)
89
+ @types << -4
90
+ @values << "<="
91
+ @types << 40 # floating point
92
+ @values << value
93
+ self
94
+ end
95
+
96
+ def equal_to(value)
97
+ @types << -4
98
+ @values << "="
99
+ @types << 40 # floating point
100
+ @values << value
101
+ self
102
+ end
103
+
104
+ def not_equal_to(value)
105
+ @types << -4
106
+ @values << "<>"
107
+ @types << 40 # floating point
108
+ @values << value
109
+ self
110
+ end
111
+
112
+ def block_reference(name = nil)
113
+ # return unless name
114
+
115
+ @types << 0
116
+ @values << "INSERT"
117
+ self
118
+ end
119
+
120
+ def name(value)
121
+ @types << [0, 2]
122
+ @values << value
123
+ self
124
+ end
125
+
126
+ def type(kind)
127
+ @types << 0
128
+ @values << kind
129
+ self
130
+ end
131
+
132
+ def layer(name)
133
+ @types << 8
134
+ @values << name
135
+ self
136
+ end
137
+
138
+ def visible(vis = true)
139
+ @types << 60
140
+ @values << (vis ? 0 : 1)
141
+ self
142
+ end
143
+
144
+ def color(num)
145
+ @types << 62 # Color number filter
146
+ @values << num
147
+ self
148
+ end
149
+
150
+ def paper_space
151
+ @types << 67 # Paper space filter
152
+ @values << 1
153
+ self
154
+ end
155
+
156
+ def model_space
157
+ @types << 67 # Model space filter
158
+ @values << 0
159
+ self
160
+ end
161
+
162
+ def contains(str)
163
+ @types << -4
164
+ @values << "<OR"
165
+
166
+ # Filter for TEXT
167
+ @types << 1 # Text string group code for TEXT
168
+ @values << "*#{str}*"
169
+
170
+ # Filter for MTEXT
171
+ @types << 1 # Text string group code for MTEXT
172
+ @values << "*#{str}*"
173
+
174
+ @types << -4
175
+ @values << "OR>"
176
+
177
+ self
178
+ end
179
+ end
180
+ end
@@ -0,0 +1,61 @@
1
+ # require_relative "selection_filter"
2
+ require_relative 'filter'
3
+
4
+ module Autocad
5
+ class SelectionSet
6
+ attr_reader :filter_types, :filter_values, :name
7
+
8
+ def initialize(name)
9
+ @name = name
10
+ @filter_types = []
11
+ @filter_values = []
12
+ end
13
+
14
+ def has_filter?
15
+ filter_types && filter_types.any?
16
+ end
17
+
18
+ def filter_text(str = nil)
19
+ if str
20
+ filter_text_containing(str)
21
+ else
22
+ filter do |f|
23
+ f.or(f.type('TEXT'), f.type('MTEXT'))
24
+ end
25
+ end
26
+ end
27
+
28
+ # filter do |f|
29
+ # st = f.type('Circle').or(f.type('Arc'))
30
+ # st2 = f.layer('0').or(f.layer('1'))
31
+ # f.and(st, st2)
32
+ # end
33
+ def filter
34
+ if block_given?
35
+ filter = Filter.new
36
+ result = yield filter
37
+ @filter_types, @filter_values = result.convert_clauses
38
+ end
39
+ self
40
+ end
41
+
42
+ # Helper methods for common operations
43
+ def filter_by_type(*types)
44
+ filter { |f| f.or(*types.map { |t| f.type(t) }) }
45
+ end
46
+
47
+ def filter_by_layer(*layers)
48
+ filter { |f| f.or(*layers.map { |l| f.layer(l) }) }
49
+ end
50
+
51
+ def filter_text_containing(text)
52
+ filter do |f|
53
+ f.and(f.has_text(text), f.or(f.type('TEXT'), f.type('MTEXT')))
54
+ end
55
+ end
56
+
57
+ def filter_block_references(name = nil)
58
+ filter { |f| f.block_reference(name) }
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,146 @@
1
+ module Autocad
2
+ class SelectionSetAdapter
3
+ def self.from_ole_obj(drawing, ole)
4
+ ss = SelectionSet.new(ole.Name)
5
+ new(drawing, ss, ole)
6
+ end
7
+
8
+ attr_reader :ole_obj, :drawing, :selection_set
9
+
10
+ def initialize(drawing, selection_set, ole = nil)
11
+ @drawing = drawing
12
+ @selection_set = selection_set
13
+ @ole_obj = ole || create_selection_set
14
+ end
15
+
16
+ def delete
17
+ @ole_obj.Delete
18
+ @selection_set = nil
19
+ end
20
+
21
+ # checks if the selection set has any items
22
+ # @ rbs return bool
23
+ def has_items?
24
+ ole_obj.Count > 0
25
+ end
26
+
27
+ def count
28
+ ole_obj.Count
29
+ end
30
+
31
+ def clear
32
+ ole_obj.Clear
33
+ end
34
+
35
+ def filter_text(str)
36
+ @selection_set.filter_text(str)
37
+ end
38
+
39
+ def filter_text_containing(str)
40
+ @selection_set.filter_text_containing(str)
41
+ end
42
+
43
+ def app
44
+ @drawing.app
45
+ end
46
+
47
+ def each
48
+ return to_enum(__callee__) unless block_given?
49
+
50
+ ole_obj.each { |o| yield app.wrap(o) }
51
+ end
52
+
53
+ def name
54
+ @ole_obj.Name
55
+ end
56
+
57
+ def filter_types
58
+ @selection_set.filter_types
59
+ end
60
+
61
+ def filter_values
62
+ @selection_set.filter_values
63
+ end
64
+
65
+ def select_on_screen(ft = ole_filter_types, fv = ole_filter_values)
66
+ @ole_obj.SelectOnScreen(ft, fv)
67
+ end
68
+
69
+ def select(mode: :all, pt1: nil, pt2: nil, ft: ole_filter_types, fv: ole_filter_values)
70
+ acad_mode = case mode
71
+ when :all
72
+ ACAD::AcSelectionSetAll
73
+ when :window
74
+ ACAD::AcSelectionSetWindow
75
+ when :crossing
76
+ ACAD::AcSelectionSetCrossing
77
+ when :previous
78
+ ACAD::AcSelectionSetPrevious
79
+ when :last
80
+ ACAD::AcSelectionSetLast
81
+ else
82
+ Acad::AcSelectionSetAll
83
+ end
84
+ @ole_obj.Select(acad_mode, nil, nil, ft, fv)
85
+ end
86
+
87
+ # accepts Point3d | [x,y] | (x,y)
88
+ def select_at_point(x, y)
89
+ point = if x.respond_to?(:x) && x.respond_to?(:y)
90
+ # Handle Point3d object
91
+ [x.x, x.y]
92
+ elsif x.is_a?(Array)
93
+ # Handle array input
94
+ x
95
+ else
96
+ # Handle separate x,y coordinates
97
+ [x, y]
98
+ end
99
+
100
+ @ole_obj.SelectAtPoint(point, filter_types, filter_values)
101
+ end
102
+
103
+ # @param points [Array<Point3d>] Array of points defining the polygon
104
+ # @param mode [:fence, :window, :crossing] Selection mode
105
+ def select_by_polygon(points: [], mode: :fence)
106
+ # Convert points to arrays of coordinates
107
+ point_coords = points.map { |p| [p.x, p.y] }
108
+
109
+ mode_code = case mode
110
+ when :fence then 5
111
+ when :window then 3
112
+ when :crossing then 4
113
+ else
114
+ raise ArgumentError, "Invalid selection mode: #{mode}. Must be :fence, :window, or :crossing"
115
+ end
116
+
117
+ @ole_obj.SelectByPolygon(mode_code, point_coords, filter_types, filter_values)
118
+ end
119
+
120
+ def filter(&)
121
+ @selection_set.filter(&)
122
+ end
123
+
124
+ private
125
+
126
+ def create_selection_set
127
+ @drawing.ole_obj.SelectionSets.Add(@selection_set.name)
128
+ end
129
+
130
+ def ole_filter_types
131
+ WIN32OLE::Variant.new(filter_types, WIN32OLE::VARIANT::VT_ARRAY | WIN32OLE::VARIANT::VT_I2)
132
+ end
133
+
134
+ def ole_filter_values
135
+ WIN32OLE::Variant.new(filter_values, WIN32OLE::VARIANT::VT_ARRAY | WIN32OLE::VARIANT::VT_VARIANT)
136
+ end
137
+ end
138
+ end
139
+
140
+ # ss = Autocad::SelectionSet.new('test_ss')
141
+ # ss.filter_text_containing('test')
142
+ # ss = drawing.create_selection_set('test_ss') do
143
+ # filter do |f|
144
+ # f.or(f.type('Circle'), f.type('Arc'))
145
+ # end
146
+ # end
@@ -0,0 +1,74 @@
1
+ require_relative "element"
2
+
3
+ module Autocad
4
+ class Text < Element
5
+ def read_ole(_ole)
6
+ ole_obj.TextString
7
+ end
8
+
9
+ def write_ole(text)
10
+ ole_obj.TextString = text
11
+ end
12
+
13
+ def to_regexp
14
+ Regexp.new(read_ole.to_s)
15
+ end
16
+
17
+ def =~(reg)
18
+ @original =~ reg
19
+ end
20
+
21
+ # de_relativef tocad_id
22
+ # @ole_obj.Id || @ole_obj.ID64
23
+ # end
24
+ # def text?
25
+ # true
26
+ # end
27
+
28
+ # def text_node?
29
+ # false
30
+ # end
31
+
32
+ def to_s
33
+ original.to_s
34
+ end
35
+
36
+ def bounds
37
+ binding.break
38
+ rotation = ole_obj.Rotation
39
+ begin
40
+ app_ole_obj.Matrix3dInverse(rotation)
41
+ rescue
42
+ binding.irb
43
+ end
44
+ transform = app_ole_obj.Transform3dFromMatrix3dandFixedPoint3d(app_ole_obj.Matrix3dInverse(rotation),
45
+ ole_obj.origin)
46
+ ole_obj.transform transform
47
+
48
+ 0.upto(4) do |i|
49
+ points[i] = ole_obj.Boundary.Low
50
+ end
51
+ points[2] = self.Boundary.High
52
+ points[1].X = points[2].x
53
+ points[3].y = points[2].Y
54
+ end
55
+
56
+ def method_missing(meth, *, &)
57
+ if /^[A-Z]/.match?(meth)
58
+ ole_obj.send(meth, *)
59
+ else
60
+ dup = @original.dup
61
+ result = dup.send(meth, *, &)
62
+ update(result)
63
+ result
64
+ end
65
+ end
66
+
67
+ # def method_missing(meth,*args,&block)
68
+ # dup = @original_text.dup
69
+ # result = dup.send(meth,*args, &block)
70
+ # _update(dup) unless dup == @original_text
71
+ # result
72
+ # end
73
+ end
74
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Autocad
4
+ VERSION = '0.4.6'
5
+ end
data/lib/autocad.rb ADDED
@@ -0,0 +1,161 @@
1
+ # rbs_inline: enabled
2
+
3
+ module Autocad
4
+ module Common
5
+ def method_missing(method, ...)
6
+ if /^[A-Z]/.match?(method.to_s)
7
+ ole_obj.send(method, ...)
8
+ else
9
+ super
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ module ACAD
16
+ end
17
+
18
+ require "logger"
19
+ require "autocad/version"
20
+ require "win32ole"
21
+ require "pathname"
22
+ require "autocad/app"
23
+ require "autocad/errors"
24
+ require "autocad/point3d"
25
+ require "autocad/layer"
26
+ require "autocad/message_box"
27
+
28
+ def Point3d(...)
29
+ Autocad::Point3d.new(...)
30
+ end
31
+
32
+ module Autocad
33
+ ROOT = Pathname.new(__dir__).parent
34
+
35
+ class << self
36
+ # @yield [Autocad::App]
37
+ def run(...) #: void
38
+ App.run(...)
39
+ end
40
+
41
+ # @return [Pathname]
42
+ def root #:Pathname
43
+ ROOT
44
+ end
45
+
46
+ # @rbs dir: String -- the directory of drawing dgn|dwg -- to convert
47
+ # @rbs outdir: String -- the output dir for converted pdf files
48
+ def dgn2pdf(dir_or_file, outdir: dir_or_file, mode: :dir)
49
+ raise "Mode on of :dir or :file" unless [:dir, :file].include? mode
50
+ if mode == :dir
51
+ drawings = drawings_in_dir(dir_or_file)
52
+ with_drawings(drawings) do |drawing|
53
+ drawing.save_as_pdf(name: drawing.name, dir: outdir)
54
+ end
55
+ else
56
+ open_drawing(dir_or_file) do |drawing|
57
+ drawing.save_as_pdf(name: drawing.name, dir: outdir)
58
+ end
59
+ end
60
+ end
61
+
62
+ # save the current drawing
63
+ # @rbs dir: String|Pathname -- the dir to save drawing to
64
+ # @rbs exit: bool -- whether to exit afterwards or start irb
65
+ # @rbs model: bool -- prints model space instead of paperspace in pdf document
66
+ # @rbs return void
67
+ def save_open_drawings(dir: Pathname.getwd, exit: true, model: false)
68
+ if exit
69
+ run do |app|
70
+ return unless app.has_drawings?
71
+ drawings = app.drawings
72
+ drawings.each do |d|
73
+ d.copy(dir:)
74
+ d.save_as_pdf(dir:, model:)
75
+ d.close(false)
76
+ end
77
+ end
78
+ else
79
+ app = App.new
80
+ return unless app.has_drawings?
81
+ drawings = app.drawings
82
+ drawings.each do |d|
83
+ d.copy(dir:)
84
+ d.save_as_pdf(dir:, model:)
85
+ # d.close(false)
86
+ end
87
+ app
88
+ end
89
+ end
90
+
91
+ # save the current drawing
92
+ # @rbs dir: String|Dir -- the dir to save drawing to
93
+ # @rbs exit: bool -- whether to exit afterwards or start irb
94
+ # @rbs model: bool -- prints model space in pdf document
95
+ # @rbs return void
96
+ def save_current_drawing(dir, exit: true, model: false)
97
+ if exit
98
+ run do |app|
99
+ drawing = app.current_drawing
100
+ return unless drawing
101
+ drawing.copy(dir: dir)
102
+ drawing.save_as_pdf(dir:, model:)
103
+ drawing.close(false)
104
+ end
105
+ else
106
+ app = App.new
107
+ drawing = app.current_drawing
108
+ return unless drawing
109
+ drawing.copy(dir: dir)
110
+ drawing.save_as_pdf(dir: dir)
111
+ app
112
+ end
113
+ end
114
+
115
+ # save the current drawing as pdf
116
+ # @rbs dir: String|Dir -- the dir to save drawing to
117
+ # @rbs return void
118
+ def save_current_drawing_as_pdf(dir)
119
+ App.run do |app|
120
+ drawing = app.current_drawing
121
+ drawing.save_as_pdf(dir: dir)
122
+ drawing.close
123
+ end
124
+ end
125
+
126
+ # gets all dwg and dgn dfiles in a directory
127
+ # @rbs dir: String|Pathname
128
+ def drawings_in_dir(dir)
129
+ dirpath = Pathname.new(dir).expand_path
130
+ dirpath.glob("*.d{gn,wg,xf}").sort_by { _1.basename(".*").to_s.downcase }
131
+ end
132
+
133
+ def open_drawing(drawing, ...)
134
+ App.open_drawing(drawing, ...)
135
+ end
136
+
137
+ # Runs the app, opening the filenames
138
+ # and yielding each open drawing to the
139
+ # supplied block
140
+ # it automatically closes the drawing and
141
+ # the app when done
142
+ #
143
+ # @rbs *files: Array[String|Pathname]
144
+ # @rbs visible: bool -- show the app window
145
+ # @rbs error_proc: (Exception, Drawing) -> void
146
+ # @rbs wait_time: Integer -- the total amount of time to wait to open file (500)
147
+ # @rbs wait_interval: Float -- the amount of time to wait between attempts (0.5)
148
+ # @rbs read_only: bool
149
+ # @rbs &: (Drawing) -> void
150
+ def with_drawings(...)
151
+ App.with_drawings(...)
152
+ end
153
+
154
+ # Finds the drawing in dir and calls with_drawing forwarding all params
155
+ # @rbs dir: String|Pathname -- directory to search for drawings
156
+ def with_drawings_in_dir(dir, ...)
157
+ drawings = drawings_in_dir(dir)
158
+ with_drawings(drawings, ...)
159
+ end
160
+ end
161
+ end