autocad 0.4.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rubocop/minitest.yml +2 -0
- data/.rubocop/strict.yml +4 -0
- data/.rubocop.yml +33 -0
- data/.solargraph.yml +22 -0
- data/.vscode/launch.json +30 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/Guardfile +66 -0
- data/LICENSE.txt +21 -0
- data/README.md +39 -0
- data/Rakefile +10 -0
- data/Steepfile +35 -0
- data/WASD-D-TDS-C001.dwg +0 -0
- data/WASD-D-TDS-C001.pdf +0 -0
- data/autocad.log +1 -0
- data/autocad_example.rb +26 -0
- data/event_handler.log +24 -0
- data/examples/example_save_pdf.rb +5 -0
- data/exe/autocad +3 -0
- data/exe/dgn2pdf +50 -0
- data/exe/pw_print +43 -0
- data/gemfiles/rubocop.gemfile +6 -0
- data/lib/autocad/app.rb +655 -0
- data/lib/autocad/arc.rb +29 -0
- data/lib/autocad/block.rb +141 -0
- data/lib/autocad/block_reference.rb +198 -0
- data/lib/autocad/drawing.rb +426 -0
- data/lib/autocad/element.rb +454 -0
- data/lib/autocad/enumerator.rb +24 -0
- data/lib/autocad/errors.rb +37 -0
- data/lib/autocad/event_handler.rb +30 -0
- data/lib/autocad/filter.rb +168 -0
- data/lib/autocad/layer.rb +41 -0
- data/lib/autocad/line.rb +55 -0
- data/lib/autocad/message_box.rb +95 -0
- data/lib/autocad/model.rb +89 -0
- data/lib/autocad/mtext.rb +110 -0
- data/lib/autocad/paths.rb +29 -0
- data/lib/autocad/point3d.rb +143 -0
- data/lib/autocad/pviewport.rb +21 -0
- data/lib/autocad/selection_filter.rb +180 -0
- data/lib/autocad/selection_set.rb +61 -0
- data/lib/autocad/selection_set_adapter.rb +146 -0
- data/lib/autocad/text.rb +74 -0
- data/lib/autocad/version.rb +5 -0
- data/lib/autocad.rb +161 -0
- data/olegen.rb +341 -0
- data/rbs_collection.lock.yaml +188 -0
- data/rbs_collection.yaml +19 -0
- data/scanner.obj +0 -0
- data/sig/generated/autocad/app.rbs +251 -0
- data/sig/generated/autocad/arc.rbs +17 -0
- data/sig/generated/autocad/block.rbs +63 -0
- data/sig/generated/autocad/block_reference.rbs +59 -0
- data/sig/generated/autocad/drawing.rbs +158 -0
- data/sig/generated/autocad/element.rbs +166 -0
- data/sig/generated/autocad/enumerator.rbs +15 -0
- data/sig/generated/autocad/errors.rbs +23 -0
- data/sig/generated/autocad/event_handler.rbs +14 -0
- data/sig/generated/autocad/filter.rbs +60 -0
- data/sig/generated/autocad/layer.rbs +19 -0
- data/sig/generated/autocad/line.rbs +25 -0
- data/sig/generated/autocad/message_box.rbs +81 -0
- data/sig/generated/autocad/model.rbs +41 -0
- data/sig/generated/autocad/paths.rbs +19 -0
- data/sig/generated/autocad/point3d.rbs +66 -0
- data/sig/generated/autocad/selection_filter.rbs +50 -0
- data/sig/generated/autocad/selection_set.rbs +37 -0
- data/sig/generated/autocad/selection_set_adapter.rbs +28 -0
- data/sig/generated/autocad/text.rbs +19 -0
- data/sig/generated/autocad/text_node.rbs +37 -0
- data/sig/generated/autocad/version.rbs +5 -0
- data/sig/generated/autocad/viewport.rbs +11 -0
- data/sig/generated/autocad.rbs +68 -0
- data/sig/prototype/lib/autocad/app.rbs +34 -0
- data/sig/prototype/lib/autocad/block.rbs +5 -0
- data/sig/prototype/lib/autocad/block_reference.rbs +5 -0
- data/sig/prototype/lib/autocad/drawing.rbs +13 -0
- data/sig/prototype/lib/autocad/element.rbs +9 -0
- data/sig/prototype/lib/autocad/enumerator.rbs +5 -0
- data/sig/prototype/lib/autocad/event_handler.rbs +7 -0
- data/sig/prototype/lib/autocad/model.rbs +5 -0
- data/sig/prototype/lib/autocad/paths.rbs +5 -0
- data/sig/prototype/lib/autocad.rbs +3 -0
- data/temp/autocad.dwg +0 -0
- data/temp/autocad.log +1 -0
- data/temp/event_handler.log +0 -0
- metadata +147 -0
data/lib/autocad/app.rb
ADDED
@@ -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
|
data/lib/autocad/arc.rb
ADDED
@@ -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
|