aurora-dxf 0.0.3
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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +10 -0
- data/README.markdown +33 -0
- data/Rakefile +10 -0
- data/aurora-dxf.gemspec +22 -0
- data/lib/dxf.rb +25 -0
- data/lib/dxf/cluster_factory.rb +15 -0
- data/lib/dxf/entity.rb +97 -0
- data/lib/dxf/parser.rb +98 -0
- data/lib/dxf/unparser.rb +105 -0
- data/test/dxf/parser.rb +35 -0
- data/test/dxf/unparser.rb +213 -0
- data/test/fixtures/circle.dxf +24 -0
- data/test/fixtures/circle_translate.dxf +24 -0
- data/test/fixtures/square_inches.dxf +62 -0
- data/test/fixtures/square_millimeters.dxf +62 -0
- metadata +108 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a03bc384bb55b21b7c1bd910b73985797191fa05
|
4
|
+
data.tar.gz: bcebe25e0f79bd3cafc2fd0eed0486d4dc77c113
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d08d53dc672d2e65f8e1e767cb60dc880255548065255b2e1de0ce2e8ffa1c3a2c8b8e58be855df7ab8a393ae5ab232920d4dd937ccec4cb72fcf0d81018816e
|
7
|
+
data.tar.gz: b3ff2a61715effb1505ca73ce49c39782a54139167e85752f585ca30e0b51d8772b868fc52e736973a1601885f0f772e23bac532f79052cf6cffdc7a2d9f18d3
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.markdown
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# DXF
|
2
|
+
|
3
|
+
[](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
data/aurora-dxf.gemspec
ADDED
@@ -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 = "aurora-dxf"
|
7
|
+
gem.version = '0.0.3'
|
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 'aurora-geometry'
|
20
|
+
gem.add_dependency 'aurora-sketch'
|
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
|
data/lib/dxf/unparser.rb
ADDED
@@ -0,0 +1,105 @@
|
|
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
|
+
# @group Property Converters
|
38
|
+
# Convert the given value to the correct units and return it as a formatted string
|
39
|
+
# @return [String]
|
40
|
+
def format_value(value)
|
41
|
+
if value.is_a? Units::Numeric
|
42
|
+
"%g" % value.send("to_#{@units}".to_sym)
|
43
|
+
else
|
44
|
+
"%g" % value
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Emit the group codes for the center property of an element
|
49
|
+
# @param [Point] point The center point to format
|
50
|
+
def center(point, transformation)
|
51
|
+
point = transformation.transform(point) if transformation
|
52
|
+
[10, format_value(point.x), 20, format_value(point.y)]
|
53
|
+
end
|
54
|
+
|
55
|
+
# Emit the group codes for the radius property of an element
|
56
|
+
def radius(element, transformation=nil)
|
57
|
+
[40, format_value(transformation ? transformation.transform(element.radius) : element.radius)]
|
58
|
+
end
|
59
|
+
|
60
|
+
def section_end
|
61
|
+
[0, 'ENDSEC']
|
62
|
+
end
|
63
|
+
|
64
|
+
def section_start(name)
|
65
|
+
[0, 'SECTION', 2, name]
|
66
|
+
end
|
67
|
+
# @endgroup
|
68
|
+
|
69
|
+
# Convert an element to an Array
|
70
|
+
# @param [Transformation] transformation The transformation to apply to each geometry element
|
71
|
+
# @return [Array]
|
72
|
+
def to_array(element, transformation=nil)
|
73
|
+
layer = 0;
|
74
|
+
case element
|
75
|
+
when Geometry::Arc
|
76
|
+
[ 0, 'ARC', center(element.center, transformation), radius(element),
|
77
|
+
50, format_value(element.start_angle),
|
78
|
+
51, format_value(element.end_angle)]
|
79
|
+
when Geometry::Circle
|
80
|
+
[0, 'CIRCLE', 8, layer, center(element.center, transformation), radius(element)]
|
81
|
+
when Geometry::Edge, Geometry::Line
|
82
|
+
line(element.first, element.last, layer, transformation)
|
83
|
+
when Geometry::Polyline
|
84
|
+
element.edges.map {|edge| line(edge.first, edge.last, layer, transformation) }
|
85
|
+
when Geometry::Rectangle
|
86
|
+
element.edges.map {|edge| line(edge.first, edge.last, layer, transformation) }
|
87
|
+
when Geometry::Square
|
88
|
+
points = element.points
|
89
|
+
points.each_cons(2).map {|p1,p2| line(p1,p2, layer, transformation) } + line(points.last, points.first, layer, transformation)
|
90
|
+
when Sketch
|
91
|
+
transformation = transformation ? (transformation + element.transformation) : element.transformation
|
92
|
+
element.geometry.map {|e| to_array(e, transformation)}
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# Convert a {Sketch} to a DXF file and write it to the given output
|
97
|
+
# @param [IO] output A writable IO-like object
|
98
|
+
# @param [Sketch] sketch The {Sketch} to unparse
|
99
|
+
def unparse(output, sketch)
|
100
|
+
output << (section_start('HEADER') + section_end +
|
101
|
+
section_start('ENTITIES') + to_array(sketch) + section_end +
|
102
|
+
[0, 'EOF']).join("\n")
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
data/test/dxf/parser.rb
ADDED
@@ -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 '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,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,108 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: aurora-dxf
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Brandon Fosdick
|
8
|
+
- Meseker Yohannes
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-03-10 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: aurora-geometry
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - '>='
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - '>='
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: aurora-sketch
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - '>='
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - '>='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: units
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ~>
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '2.2'
|
49
|
+
type: :runtime
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ~>
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '2.2'
|
56
|
+
description: Read and write DXF files using Ruby
|
57
|
+
email:
|
58
|
+
- meseker.yohannes@gmail.com
|
59
|
+
executables: []
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- .gitignore
|
64
|
+
- Gemfile
|
65
|
+
- README.markdown
|
66
|
+
- Rakefile
|
67
|
+
- aurora-dxf.gemspec
|
68
|
+
- lib/dxf.rb
|
69
|
+
- lib/dxf/cluster_factory.rb
|
70
|
+
- lib/dxf/entity.rb
|
71
|
+
- lib/dxf/parser.rb
|
72
|
+
- lib/dxf/unparser.rb
|
73
|
+
- test/dxf/parser.rb
|
74
|
+
- test/dxf/unparser.rb
|
75
|
+
- test/fixtures/circle.dxf
|
76
|
+
- test/fixtures/circle_translate.dxf
|
77
|
+
- test/fixtures/square_inches.dxf
|
78
|
+
- test/fixtures/square_millimeters.dxf
|
79
|
+
homepage: http://github.com/meseker/dxf-ruby
|
80
|
+
licenses: []
|
81
|
+
metadata: {}
|
82
|
+
post_install_message:
|
83
|
+
rdoc_options: []
|
84
|
+
require_paths:
|
85
|
+
- lib
|
86
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - '>='
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - '>='
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
requirements: []
|
97
|
+
rubyforge_project:
|
98
|
+
rubygems_version: 2.0.3
|
99
|
+
signing_key:
|
100
|
+
specification_version: 4
|
101
|
+
summary: Tools for working with the popular DXF file format
|
102
|
+
test_files:
|
103
|
+
- test/dxf/parser.rb
|
104
|
+
- test/dxf/unparser.rb
|
105
|
+
- test/fixtures/circle.dxf
|
106
|
+
- test/fixtures/circle_translate.dxf
|
107
|
+
- test/fixtures/square_inches.dxf
|
108
|
+
- test/fixtures/square_millimeters.dxf
|