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,655 @@
1
+ # rbs_inline: enabled
2
+
3
+ require_relative "event_handler"
4
+ require_relative "drawing"
5
+ require_relative "paths"
6
+ require_relative "element"
7
+ require_relative "line"
8
+ require_relative "text"
9
+ require_relative "mtext"
10
+ require_relative "pviewport"
11
+ require_relative "block"
12
+ require_relative "block_reference"
13
+ require_relative "selection_set"
14
+
15
+ require "win32ole"
16
+ module Windows
17
+ class FileSystem
18
+ def self.windows_path(path)
19
+ obj = new
20
+ obj.windows_path(path)
21
+ end
22
+
23
+ # Convert path to windows path
24
+ # @rbs path: String, Pathname the path you want to convert
25
+ def windows_path(path)
26
+ path = path.to_path if path.respond_to? :to_path
27
+ fs_object.GetAbsolutePathName(path.to_str)
28
+ end
29
+
30
+ def fs_object
31
+ @fs_object ||= WIN32OLE.new("Scripting.FileSystemObject")
32
+ end
33
+ end
34
+ end
35
+
36
+ module Autocad
37
+ class App
38
+ include Common
39
+ @default_error_proc = ->(e, f) {
40
+ puts "Couldn't open drawing #{f}" if f
41
+ debug_error if $DEBUG
42
+ raise e
43
+ }
44
+
45
+ class << self
46
+ attr_accessor :default_error_proc
47
+
48
+ def default_app_options
49
+ {visible: false, error_proc: @default_error_proc, wait_time: 500, wait_interval: 0.5}
50
+ end
51
+
52
+ def debug_error
53
+ require "debug"
54
+ binding.break
55
+ end
56
+
57
+ # save the current drawing
58
+ # @rbs dir: String|Pathname -- the dir to save drawing to
59
+ # @rbs exit: bool -- whether to exit afterwards or start irb
60
+ # @rbs model: bool -- prints model space instead of paperspace in pdf document
61
+ # @rbs return void
62
+ def save_open_drawings(dir: Pathname.getwd, exit: true, model: false)
63
+ if exit
64
+ run do |app|
65
+ return unless app.has_drawings?
66
+ drawings = app.drawings
67
+ drawings.each do |d|
68
+ d.copy(dir:)
69
+ d.save_as_pdf(dir:, model:)
70
+ d.close(false)
71
+ end
72
+ end
73
+ else
74
+ app = App.new
75
+ return unless app.has_drawings?
76
+ drawings = app.drawings
77
+ drawings.each do |d|
78
+ d.copy(dir:)
79
+ d.save_as_pdf(dir:, model:)
80
+ # d.close(false)
81
+ end
82
+ app
83
+ end
84
+ end
85
+
86
+ # Runs the app, opening the filenames
87
+ # and yielding each open drawing to the
88
+ # supplied block
89
+ # it automatically closes the drawing and
90
+ # the app when done
91
+ #
92
+ # [source]
93
+ # dir = Pathname.new('C:/templates')
94
+ # drawings = Pathname.glob(dir + '/**/*.dgn')
95
+ # App.with_drawings(drawings) do |drawing|
96
+ # drawing.save_as_pdf(dir: 'c:/output/')
97
+ # end
98
+ #
99
+ # @rbs *files: Array[String|Pathname]
100
+ # @rbs visible: bool -- show the app window
101
+ # @rbs error_proc: (Exception, Drawing) -> void
102
+ # @rbs wait_time: Integer -- the total amount of time to wait to open file (500)
103
+ # @rbs wait_interval: Float -- the amount of time to wait between attempts (0.5)
104
+ # @rbs read_only: bool
105
+ # @rbs &: (Drawing) -> void
106
+ def with_drawings(*files, visible: false, error_proc: @default_error_proc,
107
+ wait_time: 500, wait_interval: 0.5, read_only: false, &block)
108
+ # drawing_options = default_drawing_options.merge(options)
109
+ # app_options = default_app_options
110
+ files = files[0] if files[0].is_a? Array
111
+ begin
112
+ the_app = new(visible:, error_proc:, wait_time:, wait_interval:)
113
+ files_enum = files.each
114
+ loop do
115
+ file = files_enum.next
116
+ puts "opening #{file}.."
117
+ begin
118
+ the_app.open_drawing(file, read_only:, wait_time:, wait_interval:, error_proc:, &block)
119
+ the_app.ole_obj.ole_methods # check if server still open
120
+ rescue => e
121
+ raise e unless error_proc
122
+
123
+ error_proc.call(e, file)
124
+ the_app = new(visible: opt_visible)
125
+ end
126
+ end
127
+ ensure
128
+ the_app&.quit
129
+ the_app = nil
130
+ end
131
+ end
132
+
133
+ # gets all dwg and dgn files in the directory given by
134
+ # dir_or_file or gets the file given by dir_or_file
135
+ # and saves them as pdf files in the outdir
136
+ # @rbs dir_or_file: String the directory of drawing [dgn,dwg] to convert
137
+ # @rbs outdir: String the output dir for converted pdf files
138
+ # @rbs return void
139
+ def dwg2pdf(dir_or_file, outdir: dir_or_file, mode: :dir)
140
+ raise "Mode on of :dir or :file" unless [:dir, :file].include? mode
141
+ if mode == :dir
142
+ drawings = drawings_in_dir(dir_or_file)
143
+ with_drawings(drawings, read_only: true) do |drawing|
144
+ drawing.save_as_pdf(name: drawing.name, dir: outdir)
145
+ end
146
+ else
147
+ open_drawing(dir_or_file) do |drawing|
148
+ drawing.save_as_pdf(name: drawing.name, dir: outdir)
149
+ end
150
+ end
151
+ end
152
+
153
+ # Initialize an instance of app with the options
154
+ # @rbs : Hash] options the options to create the app with
155
+ # @option options bool :visible Is the app visible
156
+ #
157
+ # [source]
158
+ # ----
159
+ # App.run do |app|
160
+ # drawing = app.open_drawing('test.dgn')
161
+ # drawing.scan_all_text do |model,text|
162
+ # puts "#{model} #{text}"
163
+ # end
164
+ # end
165
+ # @rbs options: Hash[Symbol,Object]
166
+ # @rbs &: (App) -> void -- the_app yields the instanciated app
167
+ def run(options = {}) #: void
168
+ opts = default_app_options.merge(options)
169
+ err_fn = opts.fetch(:error_proc, default_error_proc)
170
+ begin
171
+ the_app = new(**opts)
172
+ # binding.break if the_app.nil?
173
+ yield the_app
174
+ rescue => e
175
+ if e.respond_to? :drawing
176
+ err_fn.call(e, e.drawing)
177
+ else
178
+ err_fn.call(e, nil)
179
+ end
180
+ ensure
181
+ the_app&.quit
182
+ GC.start
183
+ end
184
+ end
185
+
186
+ # Calls #run to get an app instance then call open drawing with
187
+ # that app
188
+ # (see #open_drawing)
189
+ # @rbs &block: { (Drawing) -> void }
190
+ def open_drawing(drawing, **options, &block) #: void
191
+ run(**options) do |app|
192
+ app.open_drawing(drawing, **options, &block)
193
+ end
194
+ end
195
+ end
196
+
197
+ # @rbs return bool -- true if there is an active drawing
198
+ def active_drawing?
199
+ ole_obj.Documents.count > 0
200
+ end
201
+
202
+ # @rbs return Drawing | nil -- returns drawing if active_drawing
203
+ def active_drawing
204
+ return unless active_drawing?
205
+ ole = ole_obj.ActiveDocument
206
+ drawing_from_ole(ole)
207
+ end
208
+
209
+ def drawing_from_ole(ole) #: Drawing
210
+ Drawing.new(self, ole)
211
+ end
212
+
213
+ attr_reader :error_proc, :visible, :logger
214
+
215
+ # Constructor for app
216
+ # @rbs visible: bool -- do you want the app to be visible
217
+ # @rbs event_handler: EventHandler
218
+ def initialize(visible: true, error_proc: self.class.default_error_proc, event_handler: default_event_handler, wait_interval: nil, wait_time: nil)
219
+ @visible = visible
220
+ @logger = Logger.new("autocad.log")
221
+ @event_handler = event_handler
222
+ @error_proc = error_proc
223
+ @ole_obj, @app_event = init_ole_and_app_event(visible: @visible, event_handler: @event_handler, tries: 5,
224
+ sleep_duration: 0.5)
225
+ @run_loop = true
226
+ @windows = Windows::FileSystem.new
227
+ # make_visible(visible)
228
+ @scanners = {}
229
+ rescue => e
230
+ @error_proc.call(e, nil)
231
+ end
232
+
233
+ def windows_path(path)
234
+ @windows.windows_path(path)
235
+ end
236
+
237
+ def wrap(item, cell = nil)
238
+ Element.convert_item(item, self, cell)
239
+ end
240
+
241
+ # the default EventHandler
242
+ #
243
+ # @rbs return EventHandler -- returns the default EventHandler
244
+ def default_event_handler
245
+ event_handler = EventHandler.new
246
+ # event_handler.add_handler("BeginOpen") do |*args|
247
+ # puts "begining opening drawing #{args}"
248
+ # end
249
+ event_handler.add_handler("EndOpen") do |*args|
250
+ puts "drawing #{args} opened"
251
+ @drawing_opened = true
252
+ end
253
+ event_handler.add_handler("BeginDocClose") do |*args|
254
+ @drawing_opened = false
255
+ puts "drawing #{args} closed"
256
+ end
257
+
258
+ event_handler.add_handler("NewDrawing") do |*args|
259
+ @drawing_opened = true
260
+ puts "drawing #{args} created"
261
+ end
262
+ event_handler
263
+ end
264
+
265
+ def default_app_options
266
+ self.class.default_app_options
267
+ end
268
+
269
+ # register an handler
270
+ #
271
+ # @rbs event: String -- event to registor for
272
+ def register_handler(event, &)
273
+ @event_handler.add_handler(event, &) unless event == "OnQuit"
274
+ end
275
+
276
+ #
277
+ # return a Handler
278
+ #
279
+ # @rbs : String,Symbol] event the event key
280
+ #
281
+ # @rbs return Proc returns the Proc given by event name
282
+ #
283
+ def get_handler(event)
284
+ @event_handler.get_handler(event)
285
+ end
286
+
287
+ def load_constants(ole)
288
+ WIN32OLE.const_load(ole, ACAD) unless ACAD.constants.size > 0
289
+ end
290
+
291
+ def run_loop
292
+ WIN32OLE_EVENT.message_loop if @run_loop
293
+ end
294
+
295
+ def stop_loop
296
+ @run_loop = false
297
+ end
298
+
299
+ def exit_message_loop
300
+ puts "Autocad exiting..."
301
+ @run_loop = false
302
+ end
303
+
304
+ def visible?
305
+ @visible
306
+ end
307
+
308
+ def visible=(value)
309
+ make_visible !!value
310
+ end
311
+
312
+ def make_visible(visible)
313
+ @visible = visible
314
+ begin
315
+ @ole_obj.Visible = visible
316
+ true
317
+ rescue
318
+ false
319
+ end
320
+ end
321
+
322
+ # Zooms the current viewport to display the entire drawing
323
+ def zoom_all
324
+ ole_obj.ZoomAll
325
+ end
326
+
327
+ def zoom_center(center, magnify: 1.0)
328
+ pt = Point3d(center)
329
+ ole_obj.ZoomCenter(pt.to_ole, magnify.to_f)
330
+ end
331
+
332
+ def zoom_window(pt1, pt2)
333
+ pt1 = Point3d(pt1)
334
+ pt2 = Point3d(pt2)
335
+ ole_obj.ZoomWindow(pt1.to_ole, pt2.to_ole)
336
+ end
337
+
338
+ def zoom_pick_window
339
+ ole_obj.ZoomPickWindowo
340
+ end
341
+
342
+ def zoom_extents
343
+ ole_obj.ZoomExtents
344
+ end
345
+
346
+ def zoom_previous
347
+ ole_obj.ZoomPrevious
348
+ end
349
+
350
+ def zoom_scaled(magnify: 1.0, scale_type: :paper_space)
351
+ scale_type = case scale_type
352
+ when :paper_space
353
+ ACAD::AcZoomScaledRelativePSpace
354
+ when :absolute
355
+ ACAD::AcZoomScaledAbsolute
356
+ when :relative
357
+ ACAD::AcZoomScaledRelative
358
+ else
359
+ ACAD::AcZoomScaledRelative
360
+ end
361
+ ole_obj.ZoomScaled(magnify.to_f, scale_type)
362
+ end
363
+
364
+ # Zooms the current viewport to a specific center point and magnify factor
365
+ # @rbs center: Point3d | [Float, Float, Float| nil] -- center of zoom
366
+ # @rbs magnify: Float
367
+ def zoom_center(center, magnify: 1.0)
368
+ pt = Point3d(center)
369
+ ole_obj.ZoomCenter(pt.to_ole, magnify.to_f)
370
+ end
371
+
372
+ def ole_obj
373
+ is_ok = true
374
+ begin
375
+ @ole_obj.Visible
376
+ rescue
377
+ is_ok = false
378
+ end
379
+
380
+ @ole_obj, @app_event = init_ole_and_app_event(visible: @visible, event_handler: @event_handler, tries: 3) unless is_ok
381
+
382
+ @ole_obj
383
+ end
384
+
385
+ def quit
386
+ close_all_drawings
387
+ @ole_obj&.Quit
388
+ rescue
389
+ nil
390
+ end
391
+
392
+ def close_all_drawings(save: false)
393
+ return unless @ole_obj
394
+ until @ole_obj.Documents.Count == 0
395
+ begin
396
+ @ole_obj.ActiveDocument.Close(save)
397
+ rescue
398
+ break
399
+ end
400
+ end
401
+ end
402
+
403
+ def close_active_drawing
404
+ drawing = active_drawing
405
+ drawing&.close
406
+ end
407
+
408
+ # create a new drawing
409
+ #
410
+ # @rbs filename: String | Pathname -- The name of the drawing.
411
+ # @rbs seedfile: String -- The name of the seed file.
412
+ # should not include a path. The default ggextension is ".dgn".
413
+ # Typical values are "seed2d" or "seed3d".
414
+ # @rbs open: bool -- If the open argument is True,
415
+ # CreateDesignFile returns the newly-opened DesignFile object;
416
+ # this is the same value as ActiveDesignFile. If the Open argument is False,
417
+ # CreateDesignFile returns Nothing.
418
+ # @rbs return Drawing, void -- returns the new drawing
419
+ def new_drawing(filename, open: true, options: {}, &block)
420
+ opts = default_app_options.merge(options)
421
+ err_fn = opts.fetch(:error_proc, error_proc)
422
+ file_path = Pathname.new(filename).expand_path
423
+ raise ExistingFile, file_path if file_path.exist?
424
+
425
+ # drawing_name = normalize_name(filename)
426
+ # seedfile = determine_seed(seedfile)
427
+ # binding.break unless seedfile
428
+ windows_name = windows_path(filename)
429
+ ole = new_ole_drawing(windows_name, open: open, wait_time: opts[:wait_time], wait_interval: opts[:wait_interval])
430
+ drawing = drawing_from_ole(ole)
431
+ return drawing unless block
432
+
433
+ begin
434
+ yield drawing
435
+ rescue DrawingError => e
436
+ err_fn.call(e, e.drawing)
437
+ rescue => e
438
+ err_fn.call(e, file_path)
439
+ ensure
440
+ drawing.close
441
+ end
442
+ end
443
+
444
+ # open the drawing
445
+ # @rbs filename: String the name of the file to open
446
+ # @rbs : bool :read_only (false)
447
+ # @rbs wait_time: Integer -- the total amount of time to wait to open file (500)
448
+ # @rbs wait_interval: Float -- the amount of time in seconds to wait before retry (0.5)
449
+ # @rbs error_proc: Proc -- a proc to run
450
+ # @rbs &: (Drawing) -> (void)
451
+ # @rbs return Drawing | void
452
+ def open_drawing(filename, read_only: false, wait_time: nil,
453
+ wait_interval: nil, error_proc: nil, &block)
454
+ file_path = Pathname.new(filename).expand_path
455
+ raise FileNotFound.new(file_path) unless file_path.file?
456
+
457
+ begin
458
+ ole = ole_open_drawing(windows_path(filename), read_only:, wait_time:, wait_interval:)
459
+ rescue DrawingError => e
460
+ raise e unless err_fn
461
+
462
+ err_fn.call(e, e.drawing)
463
+ end
464
+ drawing = drawing_from_ole(ole)
465
+ return drawing unless block_given?
466
+
467
+ begin
468
+ yield drawing
469
+ rescue => e
470
+ raise e unless err_fn
471
+ err_fn.call(e, filename)
472
+ ensure
473
+ drawing.close
474
+ end
475
+ end
476
+
477
+ alias_method :doc, :active_drawing
478
+
479
+ alias_method :current_drawing, :active_drawing
480
+
481
+ def model_space
482
+ ModelSpace.new(doc_ole.ModelSpace)
483
+ end
484
+
485
+ def paper_space
486
+ PaperSpace.new(doc_ole.PaperSpace)
487
+ end
488
+
489
+ alias_method :model, :model_space
490
+
491
+ # @rbs message: String -- the String to put in Autocad prompt
492
+ def prompt(message)
493
+ doc.prompt(message)
494
+ end
495
+
496
+ # @rbs prompt: string -- the string to prompt the user for string
497
+ # @rbs has_spaces: bool -- whether the string returned can contain spaces
498
+ def get_input_string(...)
499
+ doc.get_input_string(...)
500
+ end
501
+
502
+ # @rbs prompt: string -- the string to prompt the user for integer
503
+ def get_input_integer(...)
504
+ doc.get_input_integer(...)
505
+ end
506
+
507
+ # In a running Autocad instance, prompts the user for a point.
508
+ # Uses the prompt argument as the prompt string.
509
+ # If base_point is provided, it is used as the base point and a
510
+ # stretched line is drawn from the base point to the returned point.
511
+ # @rbs prompt: String
512
+ # @rbs base_point: Array, Point3d, nil
513
+ # @rbs return [Point3d]
514
+ def get_point(...)
515
+ doc.get_point(...)
516
+ end
517
+
518
+ # In autocad prompts the user for a selection.
519
+ # @rbs prompt: String the prompt that displays in Autocad
520
+ # @rbs name: String the name of the selection
521
+ # @rbs return [SelectionSet]
522
+ def get_selection(prompt: "Select objects", name: "_SS1")
523
+ prompt(prompt)
524
+ begin
525
+ doc_ole.SelectionSets.Item(name).Delete
526
+ rescue
527
+ logger.debug("Delete selection failed")
528
+ end
529
+
530
+ selection = doc_ole.SelectionSets.Add(name)
531
+ selection.SelectOnScreen
532
+ selection
533
+ end
534
+
535
+ def has_documents?
536
+ ole_obj.Documents.Count > 0
537
+ end
538
+
539
+ alias_method :has_drawings?, :has_documents?
540
+
541
+ # @rbs return Enumerator[Drawing] | void
542
+ # @rbs &: (Drawing) -> void
543
+ def documents
544
+ return to_enum(__callee__) unless block_given?
545
+ ole_obj.Documents.each { |o| yield Drawing.new(self, o) }
546
+ end
547
+
548
+ alias_method :drawings, :documents
549
+
550
+ # @rbs return [bool] true
551
+ def drawing_opened?
552
+ @drawing_opened
553
+ end
554
+
555
+ # @rbs return [Pathname] Autocad Files.TemplateDwgPath
556
+ def templates_path
557
+ Pathname.new(ole_preferences_files.TemplateDwgPath)
558
+ end
559
+
560
+ def templates
561
+ return enum_for(:templates) unless block_given?
562
+
563
+ templates_path.children.each do |template|
564
+ yield template if template.file?
565
+ end
566
+ end
567
+
568
+ # Set Autocad Files.TemplateDwgPath
569
+ # @rbs path: Pathname, String the location on disk for Autocad templates
570
+ def template_path=(path)
571
+ ole_preferences_files.TemplateDwgPath = path.to_s
572
+ end
573
+
574
+ # @rbs return [Array<Pathname>] all paths in Files.SupportPath
575
+ def support_paths
576
+ ole_preferences_files.SupportPath.split(";").map { |f| Pathname.new(f) }
577
+ end
578
+
579
+ # @rbs return [Array<Pathname>] all paths in Files.PrinterConfigPath
580
+ def printer_config_paths
581
+ ole_preferences_files.PrinterConfigPath.split(";").map { |f| Pathname.new(f) }
582
+ end
583
+
584
+ # from the printer_config_paths, return all plotcfg files
585
+ # @rbs return [Enumerator[String]]
586
+ def plot_configs
587
+ return enum_for(:plot_configs) unless block_given?
588
+ printer_config_paths.each do |path|
589
+ path.children.each do |plot|
590
+ yield plot.to_s if plot.file?
591
+ end
592
+ end
593
+ end
594
+
595
+ private
596
+
597
+ def ole_preferences_files
598
+ @ole_preferences_files ||= ole_obj.Preferences.Files
599
+ end
600
+
601
+ def send_command(command)
602
+ ole_obj.SendCommand command
603
+ end
604
+
605
+ def init_ole_and_app_event(visible: @visible, event_handler: @event_handler, tries: 5, sleep_duration: 1)
606
+ ole = nil
607
+ begin
608
+ ole = WIN32OLE.connect("Autocad.Application")
609
+ rescue WIN32OLERuntimeError
610
+ ole = WIN32OLE.new("Autocad.Application")
611
+ end
612
+
613
+ sleep(sleep_duration)
614
+ # ole.Visible = visible
615
+ # ole.IsProcessLocked = true
616
+ load_constants(ole)
617
+ app_event = WIN32OLE_EVENT.new(ole)
618
+ app_event.handler = event_handler
619
+ [ole, app_event]
620
+ rescue => e
621
+ tries -= 1
622
+ sleep_duration += 1.5
623
+ puts "Error: #{e}. #{tries} tries left."
624
+ retry if tries.positive?
625
+ raise e, "unable to init ole app"
626
+ end
627
+
628
+ def doc_ole
629
+ ole_obj.ActiveDocument
630
+ end
631
+
632
+ def new_ole_drawing(filename, open: true, wait_time: 500, wait_interval: 0.5)
633
+ ole = ole_obj.Documents.add(filename)
634
+ wait_drawing_opened(wait_time, wait_interval)
635
+ return ole if drawing_opened?
636
+ raise DrawingError.new("New drawing not opened in #{wait_time} seconds", filename)
637
+ end
638
+
639
+ def ole_open_drawing(filename, read_only: false, wait_time: 500, wait_interval: 0.5)
640
+ ole = ole_obj.Documents.Open(filename, read_only)
641
+ wait_drawing_opened(wait_time: wait_time, wait_interval: wait_interval)
642
+ return ole if drawing_opened?
643
+ raise DrawingError.new("drewing not opened in #{wait_time}", path) unless drawing_opened?
644
+ end
645
+
646
+ def wait_drawing_opened(secs, interval = 1)
647
+ elapsed = 0
648
+ while !drawing_opened? && elapsed <= secs
649
+ elapsed += interval
650
+ sleep(interval)
651
+ run_loop
652
+ end
653
+ end
654
+ end
655
+ end
@@ -0,0 +1,29 @@
1
+ require_relative "element"
2
+
3
+ module Autocad
4
+ class Arc < Element
5
+ def length
6
+ @ole_obj.ArcLength
7
+ end
8
+
9
+ def start_point
10
+ Point3d(ole_obj.StartPoint)
11
+ end
12
+
13
+ def end_point
14
+ Point3d(ole_obj.EndPoint)
15
+ end
16
+
17
+ def start_angle
18
+ @ole_obj.StartAngle
19
+ end
20
+
21
+ def end_angle
22
+ @ole_obj.EndAngle
23
+ end
24
+
25
+ def total_angle
26
+ @ole_obj.TotalAngle
27
+ end
28
+ end
29
+ end