Class: Tsf::Vector
- Inherits:
-
Object
- Object
- Tsf::Vector
- Defined in:
- lib/tsf/vector.rb
Overview
Loads a TSF file and parses its content
Instance Attribute Summary collapse
-
#bitmap ⇒ Object
readonly
Returns the value of attribute bitmap.
-
#grouped_data ⇒ Object
readonly
Returns the value of attribute grouped_data.
-
#headers ⇒ Object
readonly
Returns the value of attribute headers.
-
#job_name ⇒ Object
readonly
Returns the value of attribute job_name.
-
#job_number ⇒ Object
readonly
Returns the value of attribute job_number.
-
#loaded ⇒ Object
readonly
Returns the value of attribute loaded.
-
#material_group ⇒ Object
readonly
Returns the value of attribute material_group.
-
#material_name ⇒ Object
readonly
Returns the value of attribute material_name.
-
#polygons ⇒ Object
readonly
Returns the value of attribute polygons.
-
#resolution ⇒ Object
readonly
Returns the value of attribute resolution.
-
#size ⇒ Object
readonly
Returns the value of attribute size.
Class Method Summary collapse
-
.load_tsf(data) ⇒ Object
Data is the raw data from the TSF file.
Instance Method Summary collapse
- #get_grouped_data(data) ⇒ Object
- #get_polygons(grouped_data) ⇒ Object
-
#initialize ⇒ Vector
constructor
Initialize the Vector class.
- #parse_tsf(data) ⇒ Object
Constructor Details
#initialize ⇒ Vector
Initialize the Vector class
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/tsf/vector.rb', line 8 def initialize @loaded = false @grouped_data = nil @polygons = [] @headers = [] ## Header information. Deconstructed. # Material settings for the job. @material_group = nil @material_name = nil # Job name as set in the Trotec software. @job_name = nil @job_number = nil # Usualy 500 DPI. @resoultion = nil # Will be set artboard size. when creating the tsf. @size = nil ## Image Data # Images in TSF files are stored as a monochrome bitmap. # The bitmap is used to determine the engraving area. # Image data, if present. @bitmap = nil ##### # Minimum required variables to be present in the TSF file. # CamelCase @min_vars = ['MaterialGroup', 'MaterialName', 'JobName', 'JobNumber', 'Resolution', 'Size'] end |
Instance Attribute Details
#bitmap ⇒ Object (readonly)
Returns the value of attribute bitmap.
5 6 7 |
# File 'lib/tsf/vector.rb', line 5 def bitmap @bitmap end |
#grouped_data ⇒ Object (readonly)
Returns the value of attribute grouped_data.
4 5 6 |
# File 'lib/tsf/vector.rb', line 4 def grouped_data @grouped_data end |
#headers ⇒ Object (readonly)
Returns the value of attribute headers.
4 5 6 |
# File 'lib/tsf/vector.rb', line 4 def headers @headers end |
#job_name ⇒ Object (readonly)
Returns the value of attribute job_name.
5 6 7 |
# File 'lib/tsf/vector.rb', line 5 def job_name @job_name end |
#job_number ⇒ Object (readonly)
Returns the value of attribute job_number.
5 6 7 |
# File 'lib/tsf/vector.rb', line 5 def job_number @job_number end |
#loaded ⇒ Object (readonly)
Returns the value of attribute loaded.
4 5 6 |
# File 'lib/tsf/vector.rb', line 4 def loaded @loaded end |
#material_group ⇒ Object (readonly)
Returns the value of attribute material_group.
5 6 7 |
# File 'lib/tsf/vector.rb', line 5 def material_group @material_group end |
#material_name ⇒ Object (readonly)
Returns the value of attribute material_name.
5 6 7 |
# File 'lib/tsf/vector.rb', line 5 def material_name @material_name end |
#polygons ⇒ Object (readonly)
Returns the value of attribute polygons.
4 5 6 |
# File 'lib/tsf/vector.rb', line 4 def polygons @polygons end |
#resolution ⇒ Object (readonly)
Returns the value of attribute resolution.
5 6 7 |
# File 'lib/tsf/vector.rb', line 5 def resolution @resolution end |
#size ⇒ Object (readonly)
Returns the value of attribute size.
5 6 7 |
# File 'lib/tsf/vector.rb', line 5 def size @size end |
Class Method Details
.load_tsf(data) ⇒ Object
Data is the raw data from the TSF file. data = File.read(‘path/to/file.tsf’)
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/tsf/vector.rb', line 43 def self.load_tsf(data) vector = new if data.is_a?(String) # Check if the data is empty if data.empty? raise ArgumentError, "Data is empty. Please provide a valid TSF file." end # Parse vector data vector.parse_tsf(data) else raise ArgumentError, "Expected a String, got #{data.class}" end vector end |
Instance Method Details
#get_grouped_data(data) ⇒ Object
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/tsf/vector.rb', line 103 def get_grouped_data(data) # Groups are delimited by the "BegGroup" and "EndGroup" tags. # Each group contains a list of commands or meta data. # The normal groups are: # - Header # - JobMeta # - Bitmap (optional) # - DrawCommands # Auto create nested hash when accessed. nested_group_and_values = Hash.new { |h, k| h[k] = Hash.new(&h.default_proc) } # Typically, we only get 2 levels of groups. But we can have more. current_groups = [] data.split("\n").each do |line| # a line is a command and a value. ie. <JobNumber: 1234> or <DrawPolygon: 12;0;1;2;3> # a line can define a group where value is the group name. ie. <BegGroup: Header> <EndGroup: Header> # groups can have groups (max 2.) # groups can have multple commands. # a command has only one value. command, value = line.split(":").map(&:strip).map { |s| s.gsub(/<|>/, '') } case command when "BegGroup" # Start a new group current_groups << value when "EndGroup" # End the current group current_groups.pop else # Assign the command and value to the appropriate group if current_groups.any? current = nested_group_and_values.dig(*current_groups) current[command] = value end end end nested_group_and_values end |
#get_polygons(grouped_data) ⇒ Object
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/tsf/vector.rb', line 145 def get_polygons(grouped_data) polygons = [] grouped_data['DrawCommands'].each do |key, value| polygon_string = value['DrawPolygon'] polygon_array = polygon_string.split(";") polygon = { 'id': polygon_array[0].to_i, 'color': { 'r': polygon_array[1].to_i, 'g': polygon_array[2].to_i, 'b': polygon_array[3].to_i, }, 'points': [] } polygon[:data] = polygon_array.drop(4).map(&:to_i).each_slice(2).to_a polygons << polygon end polygons end |
#parse_tsf(data) ⇒ Object
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/tsf/vector.rb', line 61 def parse_tsf(data) # Tsf files are text formatted files that repsresnte vector paths for a Troctec laser to follow. Similar to that of Gcode. # TSF file use a xml-like format the prefix "BegGroup" and "EndGroup" to denote the start and end of a group of commands or meta data. # TSF files are structed it to 4 top level groups. # - Header - Contains the header information of the file. # - JobMeta - Contains meta data about the job, such as the name, date, and other information. # - Bitmap - Contains the engraving data, such as the image to be engraved. # - DrawCommands - Contains the vector data, such as the paths to be followed by the laser. # - contains many "DrawPolygon" commands, which are the actual vector paths to be followed by the laser. # - Each "DrawPolygon" command contains a list of points, which are the coordinates of the points to be followed by the laser. Delimtited by a ;. # - The first 4 digits of the command contain, ID, then R,G,B color values of the Polygon. @grouped_data = get_grouped_data(data) # Check if the grouped data has the required groups # A TSF file is not complete if it does not have a header and draw commands. unless @grouped_data.key?('Header') || @grouped_data.key?('DrawCommands') raise ArgumentError, "Invalid TSF data. Missing required groups core groups: Header, DrawCommands" end # Check if the grouped data has the required keys missing_headers = @min_vars - @grouped_data['Header'].keys if missing_headers.any? raise ArgumentError, "Invalid TSF data. Missing required headers: #{missing_headers.join(', ')}" end @material_group = @grouped_data['Header']['MaterialGroup'] @material_name = @grouped_data['Header']['MaterialName'] @job_name = @grouped_data['Header']['JobName'] @job_number = @grouped_data['Header']['JobNumber'] @resolution = @grouped_data['Header']['Resolution'].to_i @size = @grouped_data['Header']['Size'].split(";").map(&:to_f) @polygons = get_polygons(@grouped_data) @loaded = true @grouped_data end |