├── iges ├── __init__.py ├── constants.py ├── entity.py └── curves_surfaces.py ├── README.txt ├── read_IGES.py └── LICENSE /iges/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | -------------------------------------------------------------------------------- /iges/constants.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | line_font_pattern = {None : 'Default', 0 : 'Default', 1 : 'Solid', 4 | 2 : 'Dashed', 3 : 'Phantom', 4 : 'Centerline', 5 : 'Dotted'} 5 | 6 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | An early prototype of a Python library for reading CAD files in the legacy IGES file format. 2 | 3 | https://shocksolution.com/cadcam/iges-file-reader/ 4 | 5 | IGES Format Reference: https://shocksolution.files.wordpress.com/2017/12/iges5-3_fordownload.pdf 6 | -------------------------------------------------------------------------------- /iges/entity.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | from constants import line_font_pattern 4 | 5 | def process_global_section(global_string): 6 | print global_string 7 | 8 | 9 | class Entity(): 10 | def __init__(self): 11 | self.d = dict() 12 | 13 | def add_section(self, string, key, type='int'): 14 | string = string.strip() 15 | if type == 'string': 16 | self.d[key] = string 17 | else: 18 | if len(string) > 0: 19 | self.d[key] = int(string) 20 | else: 21 | self.d[key] = None 22 | 23 | def __str__(self): 24 | s = "----- Entity -----" + os.linesep 25 | s += str(self.d['entity_type_number']) + os.linesep 26 | s += str(self.d['parameter_pointer']) + os.linesep 27 | s += str(self.d['structure']) + os.linesep 28 | s += line_font_pattern[self.d['line_font_pattern']] + os.linesep 29 | s += str(self.d['level']) + os.linesep 30 | s += str(self.d['view']) + os.linesep 31 | s += str(self.d['transform']) + os.linesep 32 | s += str(self.d['label_assoc']) + os.linesep 33 | s += str(self.d['status_number']) + os.linesep 34 | s += str(self.d['line_weight_number']) + os.linesep 35 | s += str(self.d['color_number']) + os.linesep 36 | s += str(self.d['param_line_count']) + os.linesep 37 | s += str(self.d['form_number']) + os.linesep 38 | s += str(self.d['entity_label']) + os.linesep 39 | s += str(self.d['entity_subs_num']) 40 | 41 | return s 42 | def add_parameters(self, parameters): 43 | pass 44 | 45 | 46 | -------------------------------------------------------------------------------- /iges/curves_surfaces.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from entity import Entity 3 | import os 4 | 5 | class Line(Entity): 6 | """Straight line segment""" 7 | 8 | def add_parameters(self, parameters): 9 | self.x1 = float(parameters[1]) 10 | self.y1 = float(parameters[2]) 11 | self.z1 = float(parameters[3]) 12 | self.x2 = float(parameters[4]) 13 | self.y2 = float(parameters[5]) 14 | self.z2 = float(parameters[6]) 15 | 16 | def __str__(self): 17 | s = '--- Line ---' + os.linesep 18 | s += Entity.__str__(self) + os.linesep 19 | s += "From point {0}, {1}, {2} {3}".format(self.x1, self.y1, self.z1, os.linesep) 20 | s += "To point {0}, {1}, {2}".format(self.x2, self.y2, self.z2) 21 | return s 22 | 23 | class RationalBSplineCurve(Entity): 24 | """Rational B-Spline Curve 25 | IGES Spec v5.3 p. 123 Section 4.23 26 | See also Appendix B, p. 545 27 | """ 28 | 29 | def add_parameters(self, parameters): 30 | self.K = int(parameters[1]) 31 | self.M = int(parameters[2]) 32 | self.prop1 = int(parameters[3]) 33 | self.prop2 = int(parameters[4]) 34 | self.prop3 = int(parameters[5]) 35 | self.prop4 = int(parameters[6]) 36 | 37 | self.N = 1 + self.K - self.M 38 | self.A = self.N + 2 * self.M 39 | 40 | # Knot sequence 41 | self.T = [] 42 | for i in range(7, 7 + self.A + 1): 43 | self.T.append(float(parameters[i])) 44 | 45 | # Weights 46 | self.W = [] 47 | for i in range(self.A + 8, self.A + self.K + 8): 48 | self.W.append(float(parameters[i])) 49 | 50 | # Control points 51 | self.control_points = [] 52 | for i in range(9 + self.A + self.K, 9 + self.A + 4*self.K + 1, 3): 53 | point = (float(parameters[i]), float(parameters[i+1]), float(parameters[i+2])) 54 | self.control_points.append(point) 55 | 56 | # Parameter values 57 | self.V0 = float(parameters[12 + self.A + 4 * self.K]) 58 | self.V1 = float(parameters[13 + self.A + 4 * self.K]) 59 | 60 | # Unit normal (only for planar curves) 61 | if len(parameters) > 14 + self.A + 4 * self.K + 1: 62 | self.planar_curve = True 63 | self.XNORM = float(parameters[14 + self.A + 4 * self.K]) 64 | self.YNORM = float(parameters[15 + self.A + 4 * self.K]) 65 | self.ZNORM = float(parameters[16 + self.A + 4 * self.K]) 66 | else: 67 | self.planar_curve = False 68 | 69 | def __str__(self): 70 | s = '--- Rational B-Spline Curve ---' + os.linesep 71 | s += Entity.__str__(self) + os.linesep 72 | s += str(self.T) + os.linesep 73 | s += str(self.W) + os.linesep 74 | s += str(self.control_points) + os.linesep 75 | s += "Parameter: v(0) = {0} v(1) = {1}".format(self.V0, self.V1) + os.linesep 76 | if self.planar_curve: 77 | s += "Unit normal: {0} {1} {2}".format(self.XNORM, self.YNORM, self.ZNORM) 78 | return s 79 | 80 | -------------------------------------------------------------------------------- /read_IGES.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | from iges.curves_surfaces import * # never, ever do this 4 | from iges.entity import * # or this 5 | 6 | # http://ts.nist.gov/Standards/IGES/specfigures/index.cfm 7 | 8 | # Setup 9 | fileName = 'revB_alveolus_v5a_export.igs' 10 | #fileName = 'F126x.igs' 11 | 12 | # Load 13 | f = open(fileName, 'r') 14 | 15 | param_string = '' 16 | params = [] 17 | entity_list = [] 18 | entity_index = 0 19 | displayed = False 20 | first_dict_line = True 21 | first_global_line = True 22 | first_param_line = True 23 | global_string = "" 24 | pointer_dict = {} 25 | 26 | for line in f.readlines(): 27 | data = line[:80] 28 | id_code = line[72] 29 | 30 | if id_code == 'S': # Start 31 | pass 32 | # print(data) 33 | 34 | elif id_code == 'G': # Global 35 | global_string += data # Consolidate all global lines 36 | if first_global_line: 37 | param_sep = data[2] 38 | record_sep = data[6] 39 | first_global_line = False 40 | 41 | # Record separator denotes end of global section 42 | if global_string.strip()[-1] == record_sep: 43 | process_global_section(global_string) 44 | 45 | elif id_code == 'D': # Directory entry 46 | if first_dict_line: 47 | entity_type_number = int(data[0:8].strip()) 48 | # Curve and surface entities. See IGES spec v5.3, p. 38, Table 3 49 | if entity_type_number == 100: # Circular arc 50 | e = Entity() 51 | elif entity_type_number == 102: # Composite curve 52 | e = Entity() 53 | elif entity_type_number == 104: # Conic arc 54 | e = Entity() 55 | elif entity_type_number == 108: # Plane 56 | e = Entity() 57 | elif entity_type_number == 110: # Line 58 | e = Line() 59 | elif entity_type_number == 112: # Parametric spline curve 60 | e = Entity() 61 | elif entity_type_number == 114: # Parametric spline surface 62 | e = Entity() 63 | elif entity_type_number == 116: # Point 64 | e = Entity() 65 | elif entity_type_number == 118: # Ruled surface 66 | e = Entity() 67 | elif entity_type_number == 120: # Surface of revolution 68 | e = Entity() 69 | elif entity_type_number == 122: # Tabulated cylinder 70 | e = Entity() 71 | elif entity_type_number == 124: # Transformation matrix 72 | e = Entity() 73 | elif entity_type_number == 126: # Rational B-spline curve 74 | e = RationalBSplineCurve() 75 | elif entity_type_number == 128: # Rational B-spline surface 76 | e = Entity() 77 | # Need to add more ... 78 | 79 | # CSG Entities. See IGES spec v5.3, p. 42, Section 3.3 80 | elif entity_type_number == 150: # Block 81 | e = Entity() 82 | 83 | # B-Rep entities. See IGES spec v5.3, p. 43, Section 3.4 84 | elif entity_type_number == 186: 85 | e = Entity() 86 | 87 | # Annotation entities. See IGES spec v5.3, p. 46, Section 3.5 88 | elif entity_type_number == 202: 89 | e = Entity() 90 | 91 | # Structural entities. See IGES spec v5.3, p. 50, Section 3.6 92 | elif entity_type_number == 132: 93 | e = Entity() 94 | 95 | else: 96 | e = Entity() 97 | 98 | e.add_section(data[0:8], 'entity_type_number') 99 | e.add_section(data[8:16], 'parameter_pointer') 100 | e.add_section(data[16:24], 'structure') 101 | e.add_section(data[24:32], 'line_font_pattern') 102 | e.add_section(data[32:40], 'level') 103 | e.add_section(data[40:48], 'view') 104 | e.add_section(data[48:56], 'transform') 105 | e.add_section(data[56:65], 'label_assoc') 106 | e.add_section(data[65:72], 'status_number') 107 | e.sequence_number = int(data[73:].strip()) 108 | 109 | first_dict_line = False 110 | else: 111 | e.add_section(data[8:16], 'line_weight_number') 112 | e.add_section(data[16:24], 'color_number') 113 | e.add_section(data[24:32], 'param_line_count') 114 | e.add_section(data[32:40], 'form_number') 115 | e.add_section(data[56:64], 'entity_label', type='string') 116 | e.add_section(data[64:72], 'entity_subs_num') 117 | 118 | first_dict_line = True 119 | entity_list.append(e) 120 | pointer_dict.update({e.sequence_number : entity_index}) 121 | entity_index += 1 122 | 123 | elif id_code == 'P': # Parameter data 124 | # Concatenate multiple lines into one string 125 | if first_param_line: 126 | param_string = data[:64] 127 | directory_pointer = int(data[64:72].strip()) 128 | first_param_line = False 129 | else: 130 | param_string += data[:64] 131 | 132 | if param_string.strip()[-1] == record_sep: 133 | first_param_line = True 134 | param_string = param_string.strip()[:-1] 135 | parameters = param_string.split(param_sep) 136 | entity_list[pointer_dict[directory_pointer]].add_parameters(parameters) 137 | 138 | elif id_code == 'T': # Terminate 139 | pass 140 | f.close() 141 | 142 | for entity in entity_list: 143 | if entity.d['entity_type_number'] == 126: 144 | print entity 145 | 146 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | --------------------------------------------------------------------------------