dxf-in-ruby 0.0.1

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.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'sketch-in-ruby'
6
+ gem 'units', github: 'bfoz/units-ruby'
7
+
8
+ group :test do
9
+ gem 'rake'
10
+ end
data/README.markdown ADDED
@@ -0,0 +1,33 @@
1
+ # DXF
2
+
3
+ [![Build Status](https://travis-ci.org/bfoz/dxf-ruby.png)](https://travis-ci.org/bfoz/dxf-ruby)
4
+
5
+ Tools for working with the popular DXF file format
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'DXF'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install dxf
20
+
21
+ ## Usage
22
+
23
+ ```ruby
24
+ require 'dxf'
25
+
26
+ # To export the my_sketch object in inches
27
+ DXF.write('filename.dxf', my_sketch, :inches)
28
+ ```
29
+
30
+ License
31
+ -------
32
+
33
+ Copyright 2012-2013 Brandon Fosdick <bfoz@bfoz.net> and released under the BSD license.
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+
4
+ task :default => :test
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.libs.push "lib"
8
+ t.test_files = FileList['test/**/*.rb']
9
+ t.verbose = true
10
+ end
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.name = "dxf-in-ruby"
7
+ gem.version = '0.0.1'
8
+ gem.authors = ["Brandon Fosdick", "Meseker Yohannes"]
9
+ gem.email = ["meseker.yohannes@gmail.com"]
10
+ gem.description = %q{Read and write DXF files using Ruby}
11
+ gem.summary = %q{Tools for working with the popular DXF file format}
12
+ gem.homepage = "http://github.com/meseker/dxf-ruby"
13
+
14
+ gem.files = `git ls-files`.split($/)
15
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
16
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
17
+ gem.require_paths = ["lib"]
18
+
19
+ gem.add_dependency 'geometry-in-ruby'
20
+ gem.add_dependency 'sketch-in-ruby'
21
+ gem.add_dependency 'units', '~> 2.2'
22
+ end
data/lib/dxf.rb ADDED
@@ -0,0 +1,25 @@
1
+ require_relative 'dxf/parser'
2
+ require_relative 'dxf/unparser'
3
+
4
+ module DXF
5
+ =begin
6
+ Reading and writing of files using AutoCAD's {http://en.wikipedia.org/wiki/AutoCAD_DXF Drawing Interchange File} format.
7
+
8
+ {http://usa.autodesk.com/adsk/servlet/item?siteID=123112&id=12272454&linkID=10809853 DXF Specifications}
9
+ =end
10
+
11
+ # Export a {Sketch} to a DXF file
12
+ # @param [String] filename The path to write to
13
+ # @param [Sketch] sketch The {Sketch} to export
14
+ # @param [Symbol] units Convert all values to the specified units (:inches or :mm)
15
+ def self.write(filename, sketch, units=:mm)
16
+ File.open(filename, 'w') {|f| Unparser.new(units).unparse(f, sketch)}
17
+ end
18
+
19
+ # Read a DXF file
20
+ # @param [String] filename The path to the file to read
21
+ # @return [DXF] the resulting {DXF} object
22
+ def self.read(filename)
23
+ File.open(filename, 'r') {|f| DXF::Parser.new.parse(f) }
24
+ end
25
+ end
@@ -0,0 +1,15 @@
1
+ # Include this module in the base class of a class cluster to handle swizzling
2
+ # of ::new
3
+ module ClusterFactory
4
+ def self.included(parent)
5
+ class << parent
6
+ alias :original_new :new
7
+
8
+ def inherited(subclass)
9
+ class << subclass
10
+ alias :new :original_new
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
data/lib/dxf/entity.rb ADDED
@@ -0,0 +1,97 @@
1
+ require 'geometry'
2
+
3
+ require_relative 'cluster_factory'
4
+
5
+ module DXF
6
+ # {Entity} is the base class for everything that can live in the ENTITIES block
7
+ class Entity
8
+ TypeError = Class.new(StandardError)
9
+
10
+ include ClusterFactory
11
+
12
+ attr_accessor :handle
13
+ attr_accessor :layer
14
+
15
+ def self.new(type)
16
+ case type
17
+ when 'CIRCLE' then Circle.new
18
+ when 'LINE' then Line.new
19
+ else
20
+ raise TypeError, "Unrecognized entity type '#{type}'"
21
+ end
22
+ end
23
+
24
+ def parse_pair(code, value)
25
+ # Handle group codes that are common to all entities
26
+ # These are from the table that starts on page 70 of specification
27
+ case code
28
+ when '5'
29
+ handle = value
30
+ when '8'
31
+ layer = value
32
+ else
33
+ p "Unrecognized entity group code: #{code} #{value}"
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def point_from_values(*args)
40
+ Geometry::Point[args.flatten.reverse.drop_while {|a| not a }.reverse]
41
+ end
42
+ end
43
+
44
+ class Circle < Entity
45
+ attr_accessor :x, :y, :z
46
+ attr_accessor :radius
47
+
48
+ def parse_pair(code, value)
49
+ case code
50
+ when '10' then self.x = value.to_f
51
+ when '20' then self.y = value.to_f
52
+ when '30' then self.z = value.to_f
53
+ when '40' then self.radius = value.to_f
54
+ else
55
+ super # Handle common and unrecognized codes
56
+ end
57
+ end
58
+
59
+ # @!attribute [r] center
60
+ # @return [Point] the composed center of the {Circle}
61
+ def center
62
+ a = [x, y, z]
63
+ a.pop until a.last
64
+ Geometry::Point[*a]
65
+ end
66
+ end
67
+
68
+ class Line < Entity
69
+ attr_accessor :x1, :y1, :z1
70
+ attr_accessor :x2, :y2, :z2
71
+
72
+ def parse_pair(code, value)
73
+ case code
74
+ when '10' then self.x1 = value.to_f
75
+ when '20' then self.y1 = value.to_f
76
+ when '30' then self.z1 = value.to_f
77
+ when '11' then self.x2 = value.to_f
78
+ when '21' then self.y2 = value.to_f
79
+ when '31' then self.z2 = value.to_f
80
+ else
81
+ super # Handle common and unrecognized codes
82
+ end
83
+ end
84
+
85
+ # @!attribute [r] first
86
+ # @return [Point] the starting point of the {Line}
87
+ def first
88
+ point_from_values x1, y1, z1
89
+ end
90
+
91
+ # @!attribute [r] last
92
+ # @return [Point] the end point of the {Line}
93
+ def last
94
+ point_from_values x2, y2, z2
95
+ end
96
+ end
97
+ end
data/lib/dxf/parser.rb ADDED
@@ -0,0 +1,98 @@
1
+ require_relative 'entity'
2
+
3
+ module DXF
4
+ class Parser
5
+ ParseError = Class.new(StandardError)
6
+
7
+ # @!attribute entities
8
+ # @return [Array] the entities that comprise the drawing
9
+ attr_accessor :entities
10
+
11
+ # @!attribute header
12
+ # @return [Hash] the header variables
13
+ attr_accessor :header
14
+
15
+ def initialize(units=:mm)
16
+ @entities = []
17
+ @header = {}
18
+ end
19
+
20
+ def parse(io)
21
+ parse_pairs io do |code, value|
22
+ raise ParseError, "DXF files must begin with group code 0, not #{code}" unless '0' == code
23
+ raise ParseError, "Expecting a SECTION, not #{value}" unless 'SECTION' == value
24
+ parse_section(io)
25
+ end
26
+ self
27
+ end
28
+
29
+ private
30
+
31
+ def read_pair(io)
32
+ [io.gets.chomp, io.gets.chomp]
33
+ end
34
+
35
+ def parse_pairs(io, &block)
36
+ while not io.eof?
37
+ code, value = read_pair(io)
38
+ case [code, value]
39
+ when ['0', 'ENDSEC'] then return
40
+ when ['0', 'EOF'] then return
41
+ else
42
+ yield code, value
43
+ end
44
+ end
45
+ end
46
+
47
+ def parse_section(io)
48
+ code, value = read_pair(io)
49
+ raise ParseError, 'SECTION must be followed by a section type' unless '2' == code
50
+
51
+ case value
52
+ # when 'BLOCKS'
53
+ # when 'CLASSES'
54
+ when 'ENTITIES'
55
+ parse_entities(io)
56
+ when 'HEADER'
57
+ parse_header(io)
58
+ # when 'OBJECTS'
59
+ # when 'TABLES'
60
+ # when 'THUMBNAILIMAGE'
61
+ else
62
+ raise ParseError, "Unrecognized section type '#{value}'"
63
+ end
64
+ end
65
+
66
+ # Parse the ENTITIES section
67
+ def parse_entities(io)
68
+ parse_pairs io do |code, value|
69
+ if '0' == code
70
+ entities.push Entity.new(value)
71
+ else
72
+ entities.last.parse_pair(code, value)
73
+ end
74
+ end
75
+ end
76
+
77
+ # Parse the HEADER section
78
+ def parse_header(io)
79
+ variable_name = nil
80
+ parse_pairs io do |code, value|
81
+ case code
82
+ when '9'
83
+ variable_name = value
84
+ else
85
+ header[variable_name] = parse_header_value(code, value)
86
+ end
87
+ end
88
+ end
89
+
90
+ def parse_header_value(code, value)
91
+ case code
92
+ when '2' then value # String
93
+ else
94
+ raise ParseError, "Unrecognized header value: #{code} '#{value}'"
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,118 @@
1
+ require 'geometry'
2
+ require 'sketch'
3
+ require 'units'
4
+ require 'stringio'
5
+
6
+ module DXF
7
+ class Unparser
8
+ attr_accessor :container
9
+
10
+ # Initialize with a Sketch
11
+ # @param [String,Symbol] units The units to convert length values to (:inches or :millimeters)
12
+ def initialize(units=:mm)
13
+ @units = units
14
+ end
15
+
16
+ def to_s
17
+ io = StringIO.new
18
+ unparse(io, container)
19
+ io.string
20
+ end
21
+
22
+ # @group Element Formatters
23
+ # Convert a {Geometry::Line} into group codes
24
+ def line(first, last, layer=0, transformation=nil)
25
+ first, last = Geometry::Point[first], Geometry::Point[last]
26
+ first, last = [first, last].map {|point| transformation.transform(point) } if transformation
27
+
28
+ [ 0, 'LINE',
29
+ 8, layer,
30
+ 10, format_value(first.x),
31
+ 20, format_value(first.y),
32
+ 11, format_value(last.x),
33
+ 21, format_value(last.y)]
34
+ end
35
+ # @endgroup
36
+
37
+ def text(position, content, layer=0, transformation=nil)
38
+ position = transformation.transform(position) if transformation
39
+
40
+ [0, 'TEXT',
41
+ 8, layer,
42
+ 10, format_value(position.x),
43
+ 20, format_value(position.y),
44
+ 1, content,
45
+ 7, 'NewTextStyle_4']
46
+ end
47
+
48
+ # @group Property Converters
49
+ # Convert the given value to the correct units and return it as a formatted string
50
+ # @return [String]
51
+ def format_value(value)
52
+ if value.is_a? Units::Numeric
53
+ "%g" % value.send("to_#{@units}".to_sym)
54
+ else
55
+ "%g" % value
56
+ end
57
+ end
58
+
59
+ # Emit the group codes for the center property of an element
60
+ # @param [Point] point The center point to format
61
+ def center(point, transformation)
62
+ point = transformation.transform(point) if transformation
63
+ [10, format_value(point.x), 20, format_value(point.y)]
64
+ end
65
+
66
+ # Emit the group codes for the radius property of an element
67
+ def radius(element, transformation=nil)
68
+ [40, format_value(transformation ? transformation.transform(element.radius) : element.radius)]
69
+ end
70
+
71
+ def section_end
72
+ [0, 'ENDSEC']
73
+ end
74
+
75
+ def section_start(name)
76
+ [0, 'SECTION', 2, name]
77
+ end
78
+ # @endgroup
79
+
80
+ # Convert an element to an Array
81
+ # @param [Transformation] transformation The transformation to apply to each geometry element
82
+ # @return [Array]
83
+ def to_array(element, transformation=nil)
84
+ layer = 0;
85
+ case element
86
+ when Geometry::Arc
87
+ [ 0, 'ARC', center(element.center, transformation), radius(element),
88
+ 50, format_value(element.start_angle),
89
+ 51, format_value(element.end_angle)]
90
+ when Geometry::Circle
91
+ [0, 'CIRCLE', 8, layer, center(element.center, transformation), radius(element)]
92
+ when Geometry::Text
93
+ text(element.position, element.content, layer)
94
+ when Geometry::Edge, Geometry::Line
95
+ line(element.first, element.last, layer, transformation)
96
+ when Geometry::Polyline
97
+ element.edges.map {|edge| line(edge.first, edge.last, layer, transformation) }
98
+ when Geometry::Rectangle
99
+ element.edges.map {|edge| line(edge.first, edge.last, layer, transformation) }
100
+ when Geometry::Square
101
+ points = element.points
102
+ points.each_cons(2).map {|p1,p2| line(p1,p2, layer, transformation) } + line(points.last, points.first, layer, transformation)
103
+ when Sketch
104
+ transformation = transformation ? (transformation + element.transformation) : element.transformation
105
+ element.geometry.map {|e| to_array(e, transformation)}
106
+ end
107
+ end
108
+
109
+ # Convert a {Sketch} to a DXF file and write it to the given output
110
+ # @param [IO] output A writable IO-like object
111
+ # @param [Sketch] sketch The {Sketch} to unparse
112
+ def unparse(output, sketch)
113
+ output << (section_start('HEADER') + section_end +
114
+ section_start('ENTITIES') + to_array(sketch) + section_end +
115
+ [0, 'EOF']).join("\n")
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,35 @@
1
+ require 'minitest/autorun'
2
+ require 'dxf/parser'
3
+
4
+ describe DXF::Parser do
5
+ it 'must read from an IO stream' do
6
+ File.open('test/fixtures/circle.dxf', 'r') {|f| DXF::Parser.new.parse(f) }
7
+ end
8
+
9
+ it 'must parse a file with a circle' do
10
+ parser = File.open('test/fixtures/circle.dxf', 'r') {|f| DXF::Parser.new.parse(f) }
11
+ parser.entities.length.must_equal 1
12
+ circle = parser.entities.last
13
+ circle.must_be_instance_of(DXF::Circle)
14
+ circle.center.must_equal Geometry::Point[0,0]
15
+ circle.radius.must_equal 1
16
+ end
17
+
18
+ it 'must parse a file with a translated circle' do
19
+ parser = File.open('test/fixtures/circle_translate.dxf', 'r') {|f| DXF::Parser.new.parse(f) }
20
+ parser.entities.length.must_equal 1
21
+ circle = parser.entities.last
22
+ circle.must_be_instance_of(DXF::Circle)
23
+ circle.center.must_equal Geometry::Point[1,1]
24
+ circle.radius.must_equal 1
25
+ end
26
+
27
+ it 'must parse a file with a square' do
28
+ parser = File.open('test/fixtures/square_inches.dxf', 'r') {|f| DXF::Parser.new.parse(f) }
29
+ parser.entities.length.must_equal 4
30
+ line = parser.entities.last
31
+ line.must_be_instance_of(DXF::Line)
32
+ line.first.must_equal Geometry::Point[0, 1]
33
+ line.last.must_equal Geometry::Point[0, 0]
34
+ end
35
+ end
@@ -0,0 +1,213 @@
1
+ require 'minitest/autorun'
2
+ require_relative '../../lib/dxf'
3
+
4
+ describe DXF::Unparser do
5
+ subject { DXF::Unparser.new }
6
+ let(:builder) { DXF::Unparser.new }
7
+ let(:eof) { ['0', 'EOF'] }
8
+ let(:empty_header) {['0', 'SECTION',
9
+ '2', 'HEADER',
10
+ '0', 'ENDSEC']}
11
+ let(:end_section) { ['0', 'ENDSEC'] }
12
+ let(:entities_header) { ['0', 'SECTION',
13
+ '2', 'ENTITIES'] }
14
+
15
+ describe "when give an empty Sketch object" do
16
+ it "must export a minimal file" do
17
+ builder.container = Sketch.new
18
+ builder.to_s.must_equal (empty_header + entities_header + end_section + eof).join("\n")
19
+ end
20
+ end
21
+
22
+ describe "when exporting a Sketch" do
23
+ let(:sketch) { Sketch.new }
24
+ let(:square_lines) {
25
+ ['0', 'LINE',
26
+ '8', '0',
27
+ '10', '0',
28
+ '20', '0',
29
+ '11', '1',
30
+ '21', '0',
31
+ '0', 'LINE',
32
+ '8', '0',
33
+ '10', '1',
34
+ '20', '0',
35
+ '11', '1',
36
+ '21', '1',
37
+ '0', 'LINE',
38
+ '8', '0',
39
+ '10', '1',
40
+ '20', '1',
41
+ '11', '0',
42
+ '21', '1',
43
+ '0', 'LINE',
44
+ '8', '0',
45
+ '10', '0',
46
+ '20', '1',
47
+ '11', '0',
48
+ '21', '0']
49
+ }
50
+
51
+ before do
52
+ subject.container = sketch
53
+ builder.container = sketch
54
+ end
55
+
56
+ it "with a single Arc" do
57
+ sketch.push Geometry::Arc.new center:[0,0], radius:1, start:0, end:45
58
+ builder.to_s.must_equal (empty_header + entities_header + ['0', 'ARC',
59
+ '10', '0',
60
+ '20', '0',
61
+ '40', '1',
62
+ '50', '0',
63
+ '51', '45'] + end_section + eof).join("\n")
64
+ end
65
+
66
+ it "with a single Circle" do
67
+ sketch.push Geometry::Circle.new [0,0], 1
68
+ builder.to_s.must_equal File.read('test/fixtures/circle.dxf')
69
+ end
70
+
71
+ it "with a single Line" do
72
+ sketch.push Geometry::Line[[0,0], [1,1]]
73
+ builder.to_s.must_equal (empty_header + entities_header +
74
+ ['0', 'LINE',
75
+ '8', '0',
76
+ '10', '0',
77
+ '20', '0',
78
+ '11', '1',
79
+ '21', '1'] +
80
+ end_section + eof).join("\n")
81
+ end
82
+
83
+ it "with a single Polygon" do
84
+ sketch.push Geometry::Polygon.new [0,0], [1,0], [1,1], [0,1]
85
+ builder.to_s.must_equal (empty_header + entities_header +
86
+ square_lines +
87
+ end_section + eof).join("\n")
88
+ end
89
+
90
+ it "with a single Polyline" do
91
+ sketch.push Geometry::Polyline.new [0,0], [1,0], [1,1], [0,1]
92
+ builder.to_s.must_equal (empty_header + entities_header +
93
+ square_lines[0, 36] +
94
+ end_section + eof).join("\n")
95
+ end
96
+
97
+ it "with a single Rectangle" do
98
+ sketch.push Geometry::Rectangle.new [0,0], [1,1]
99
+ builder.to_s.must_equal (empty_header + entities_header + square_lines +
100
+ end_section + eof).join "\n"
101
+ end
102
+
103
+ it "with a single Square" do
104
+ sketch.push Geometry::Rectangle.new [0,0], [1,1]
105
+ builder.to_s.must_equal (empty_header + entities_header + square_lines +
106
+ end_section + eof).join "\n"
107
+ end
108
+
109
+ it "with a group" do
110
+ Sketch::Builder.new(sketch).evaluate do
111
+ group origin:[1,1] do
112
+ circle center:[0,0], radius:1
113
+ end
114
+ end
115
+ subject.to_s.must_equal File.read('test/fixtures/circle_translate.dxf')
116
+ end
117
+
118
+ describe "when the sketch has a transformation" do
119
+ before do
120
+ sketch.transformation = Geometry::Transformation.new(origin:[2,2])
121
+ end
122
+
123
+ it "and a group" do
124
+ Sketch::Builder.new(sketch).evaluate do
125
+ group origin:[-1,-1] do
126
+ circle center:[0,0], radius:1
127
+ end
128
+ end
129
+ subject.to_s.must_equal File.read('test/fixtures/circle_translate.dxf')
130
+ end
131
+ end
132
+
133
+ describe "with a Sketch" do
134
+ let(:circle_sketch) { Sketch.new { push Geometry::Circle.new(center:[0,0], radius:1) } }
135
+
136
+ describe "without a transformation" do
137
+ it "must unparse correctly" do
138
+ sketch.push circle_sketch
139
+ builder.to_s.must_equal File.read('test/fixtures/circle.dxf')
140
+ end
141
+ end
142
+
143
+ describe "with a transformation" do
144
+ it "must unparse correctly" do
145
+ sketch.push circle_sketch, origin:[1,1]
146
+ builder.to_s.must_equal File.read('test/fixtures/circle_translate.dxf')
147
+ end
148
+ end
149
+ end
150
+
151
+ describe "when the sketch has units" do
152
+ let(:sketch) { Sketch.new }
153
+
154
+ describe "when exporting to inches" do
155
+ subject { DXF::Unparser.new :inches }
156
+ let(:square_inches) { File.read('test/fixtures/square_inches.dxf') }
157
+
158
+ before do
159
+ subject.container = sketch
160
+ end
161
+
162
+ describe "when the units are all inches" do
163
+ before do
164
+ sketch.push Geometry::Polygon.new [0.inches, 0.inches], [1.inches, 0.inches], [1.inches, 1.inches], [0.inches, 1.inches]
165
+ end
166
+
167
+ it "must not convert the values" do
168
+ subject.to_s.must_equal square_inches
169
+ end
170
+ end
171
+
172
+ describe "when the units are all metric" do
173
+ before do
174
+ sketch.push Geometry::Polygon.new [0.mm, 0.mm], [25.4.mm, 0.mm], [25.4.mm, 25.4.mm], [0.mm, 25.4.mm]
175
+ end
176
+
177
+ it "must convert the values" do
178
+ subject.to_s.must_equal square_inches
179
+ end
180
+ end
181
+ end
182
+
183
+ describe "when exporting to millimeters" do
184
+ subject { DXF::Unparser.new :mm }
185
+ let(:square_millimeters) { File.read('test/fixtures/square_millimeters.dxf') }
186
+
187
+ before do
188
+ subject.container = sketch
189
+ end
190
+
191
+ describe "when the units are all inches" do
192
+ before do
193
+ sketch.push Geometry::Polygon.new [0.inches, 0.inches], [1.inches, 0.inches], [1.inches, 1.inches], [0.inches, 1.inches]
194
+ end
195
+
196
+ it "must convert the values" do
197
+ subject.to_s.must_equal square_millimeters
198
+ end
199
+ end
200
+
201
+ describe "when the units are all metric" do
202
+ before do
203
+ sketch.push Geometry::Polygon.new [0.mm, 0.mm], [25.4.mm, 0.mm], [25.4.mm, 25.4.mm], [0.mm, 25.4.mm]
204
+ end
205
+
206
+ it "must not convert the values" do
207
+ subject.to_s.must_equal square_millimeters
208
+ end
209
+ end
210
+ end
211
+ end
212
+ end
213
+ end
@@ -0,0 +1,24 @@
1
+ 0
2
+ SECTION
3
+ 2
4
+ HEADER
5
+ 0
6
+ ENDSEC
7
+ 0
8
+ SECTION
9
+ 2
10
+ ENTITIES
11
+ 0
12
+ CIRCLE
13
+ 8
14
+ 0
15
+ 10
16
+ 0
17
+ 20
18
+ 0
19
+ 40
20
+ 1
21
+ 0
22
+ ENDSEC
23
+ 0
24
+ EOF
@@ -0,0 +1,24 @@
1
+ 0
2
+ SECTION
3
+ 2
4
+ HEADER
5
+ 0
6
+ ENDSEC
7
+ 0
8
+ SECTION
9
+ 2
10
+ ENTITIES
11
+ 0
12
+ CIRCLE
13
+ 8
14
+ 0
15
+ 10
16
+ 1
17
+ 20
18
+ 1
19
+ 40
20
+ 1
21
+ 0
22
+ ENDSEC
23
+ 0
24
+ EOF
@@ -0,0 +1,62 @@
1
+ 0
2
+ SECTION
3
+ 2
4
+ HEADER
5
+ 0
6
+ ENDSEC
7
+ 0
8
+ SECTION
9
+ 2
10
+ ENTITIES
11
+ 0
12
+ LINE
13
+ 8
14
+ 0
15
+ 10
16
+ 0
17
+ 20
18
+ 0
19
+ 11
20
+ 1
21
+ 21
22
+ 0
23
+ 0
24
+ LINE
25
+ 8
26
+ 0
27
+ 10
28
+ 1
29
+ 20
30
+ 0
31
+ 11
32
+ 1
33
+ 21
34
+ 1
35
+ 0
36
+ LINE
37
+ 8
38
+ 0
39
+ 10
40
+ 1
41
+ 20
42
+ 1
43
+ 11
44
+ 0
45
+ 21
46
+ 1
47
+ 0
48
+ LINE
49
+ 8
50
+ 0
51
+ 10
52
+ 0
53
+ 20
54
+ 1
55
+ 11
56
+ 0
57
+ 21
58
+ 0
59
+ 0
60
+ ENDSEC
61
+ 0
62
+ EOF
@@ -0,0 +1,62 @@
1
+ 0
2
+ SECTION
3
+ 2
4
+ HEADER
5
+ 0
6
+ ENDSEC
7
+ 0
8
+ SECTION
9
+ 2
10
+ ENTITIES
11
+ 0
12
+ LINE
13
+ 8
14
+ 0
15
+ 10
16
+ 0
17
+ 20
18
+ 0
19
+ 11
20
+ 25.4
21
+ 21
22
+ 0
23
+ 0
24
+ LINE
25
+ 8
26
+ 0
27
+ 10
28
+ 25.4
29
+ 20
30
+ 0
31
+ 11
32
+ 25.4
33
+ 21
34
+ 25.4
35
+ 0
36
+ LINE
37
+ 8
38
+ 0
39
+ 10
40
+ 25.4
41
+ 20
42
+ 25.4
43
+ 11
44
+ 0
45
+ 21
46
+ 25.4
47
+ 0
48
+ LINE
49
+ 8
50
+ 0
51
+ 10
52
+ 0
53
+ 20
54
+ 25.4
55
+ 11
56
+ 0
57
+ 21
58
+ 0
59
+ 0
60
+ ENDSEC
61
+ 0
62
+ EOF
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dxf-in-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Brandon Fosdick
9
+ - Meseker Yohannes
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2014-03-13 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: geometry-in-ruby
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ! '>='
29
+ - !ruby/object:Gem::Version
30
+ version: '0'
31
+ - !ruby/object:Gem::Dependency
32
+ name: sketch-in-ruby
33
+ requirement: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ! '>='
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ type: :runtime
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: units
49
+ requirement: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '2.2'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ~>
61
+ - !ruby/object:Gem::Version
62
+ version: '2.2'
63
+ description: Read and write DXF files using Ruby
64
+ email:
65
+ - meseker.yohannes@gmail.com
66
+ executables: []
67
+ extensions: []
68
+ extra_rdoc_files: []
69
+ files:
70
+ - .gitignore
71
+ - Gemfile
72
+ - README.markdown
73
+ - Rakefile
74
+ - dxf-in-ruby.gemspec
75
+ - lib/dxf.rb
76
+ - lib/dxf/cluster_factory.rb
77
+ - lib/dxf/entity.rb
78
+ - lib/dxf/parser.rb
79
+ - lib/dxf/unparser.rb
80
+ - test/dxf/parser.rb
81
+ - test/dxf/unparser.rb
82
+ - test/fixtures/circle.dxf
83
+ - test/fixtures/circle_translate.dxf
84
+ - test/fixtures/square_inches.dxf
85
+ - test/fixtures/square_millimeters.dxf
86
+ homepage: http://github.com/meseker/dxf-ruby
87
+ licenses: []
88
+ post_install_message:
89
+ rdoc_options: []
90
+ require_paths:
91
+ - lib
92
+ required_ruby_version: !ruby/object:Gem::Requirement
93
+ none: false
94
+ requirements:
95
+ - - ! '>='
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ none: false
100
+ requirements:
101
+ - - ! '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ requirements: []
105
+ rubyforge_project:
106
+ rubygems_version: 1.8.23
107
+ signing_key:
108
+ specification_version: 3
109
+ summary: Tools for working with the popular DXF file format
110
+ test_files:
111
+ - test/dxf/parser.rb
112
+ - test/dxf/unparser.rb
113
+ - test/fixtures/circle.dxf
114
+ - test/fixtures/circle_translate.dxf
115
+ - test/fixtures/square_inches.dxf
116
+ - test/fixtures/square_millimeters.dxf