00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 __title__="FreeCAD Draft Workbench - OCA importer/exporter"
00025 __author__ = "Yorik van Havre <yorik@gmx.fr>"
00026 __url__ = ["http://yorik.orgfree.com","http://free-cad.sourceforge.net"]
00027
00028 '''
00029 This script imports OCA/gcad files into FreeCAD.
00030 '''
00031
00032 import FreeCAD, os, Part, math
00033 from draftlibs import fcvec, fcgeo
00034 from FreeCAD import Vector
00035
00036 try: import FreeCADGui
00037 except ValueError: gui = False
00038 else: gui = True
00039
00040 pythonopen = open
00041 params = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
00042
00043 def getpoint(data):
00044 "turns an OCA point definition into a FreeCAD Vector"
00045 print "found point ",data
00046 if (len(data) == 3):
00047 return Vector(float(data[0]),float(data[1]),float(data[2]))
00048 elif (data[0] == "P") and (len(data) == 4):
00049 return Vector(float(data[1]),float(data[2]),float(data[3]))
00050 elif (data[0][0] == "P") and (len(data[0]) > 1):
00051 if (len(data) == 1):
00052 return objects[data[0]]
00053 else:
00054 if (data[1][0] == "R"):
00055 return objects[data[0]].add(objects[data[1]])
00056 elif (data[1][0] == "C"):
00057 return fcgeo.findProjection(objects[data[0]],objects[data[1]])
00058 elif (data[0][0] == "C"):
00059 if objects[data[0]]:
00060 p1 = objects[data[0]].Curve.Position
00061 if (len(data) == 1):
00062 return p1
00063 else:
00064 if (data[1][0] == "L"):
00065 l = objects[data[1]]
00066 return p1.add(fcgeo.vec(l))
00067
00068 def getarea(data):
00069 "turns an OCA area definition into a FreeCAD Part Wire"
00070 print "found area ",data
00071 if (data[0] == "S"):
00072 if (data[1] == "POL"):
00073 pts = data[2:]
00074 verts = []
00075 for p in pts:
00076 if (p[0] == "P"):
00077 verts.append(getpoint([p]))
00078 w = Part.makePolygon(verts)
00079 return w
00080
00081 def getarc(data):
00082 "turns an OCA arc definition into a FreeCAD Part Edge"
00083 print "found arc ", data
00084 c = None
00085 if (data[0] == "ARC"):
00086
00087 pts = data[1:]
00088 verts = []
00089 for p in range(len(pts)):
00090 if (pts[p] == "P"):
00091 verts.append(getpoint(pts[p:p+3]))
00092 elif (pts[p][0] == "P"):
00093 verts.append(getpoint([pts[p]]))
00094 if verts[0] and verts[1] and verts[2]:
00095 c = Part.Arc(verts[0],verts[1],verts[2])
00096 elif (data[0][0] == "P"):
00097
00098 verts = []
00099 rad = None
00100 for p in range(len(data)):
00101 if (data[p] == "P"):
00102 verts.append(getpoint(data[p:p+4]))
00103 elif (data[p][0] == "P"):
00104 verts.append(getpoint([data[p]]))
00105 elif (data[p] == "VAL"):
00106 rad = float(data[p+1])
00107 elif (data[p][0] == "L"):
00108 lines.append(objects[data[p]])
00109 c = Part.Circle()
00110 c.Center = verts[0]
00111 if rad: c.Radius = rad
00112 else: c.Radius = fcvec.new(verts[0],verts[1]).Length
00113 elif (data[0][0] == "L"):
00114
00115 lines = []
00116 rad = None
00117 for p in range(len(data)):
00118 if (data[p] == "VAL"):
00119 rad = float(data[p+1])
00120 elif (data[p][0] == "L"):
00121 lines.append(objects[data[p]])
00122 circles = fcgeo.circleFrom2LinesRadius(lines[0],lines[1],rad)
00123 if circles: c = circles[0]
00124 if c: return c.toShape()
00125
00126 def getline(data):
00127 print "found line ", data
00128 "turns an OCA line definition into a FreeCAD Part Edge"
00129 verts = []
00130 for p in range(len(data)):
00131 if (data[p] == "P"):
00132 verts.append(getpoint(data[p:p+4]))
00133 elif (data[p][0] == "P"):
00134 verts.append(getpoint([data[p]]))
00135 l = Part.Line(verts[0],verts[1])
00136 return l.toShape()
00137
00138 def gettranslation(data):
00139 "retrieves a transformation vector"
00140 print "found translation ",data
00141 if (data[0] == "Z"):
00142 return Vector(0,0,float(data[1]))
00143 elif (data[0] == "Y"):
00144 return Vector(0,float(data[1]),0)
00145 elif (data[0] == "X"):
00146 return Vector(float(data[1]),0,0)
00147 return Vector(0,0,0)
00148
00149 def writepoint(vector):
00150 "writes a FreeCAD vector in OCA format"
00151 return "P("+str(vector.x)+" "+str(vector.y)+" "+str(vector.z)+")"
00152
00153 def createobject(id,doc):
00154 "creates an object in the current document"
00155 if isinstance(objects[id],Part.Shape):
00156 ob = doc.addObject("Part::Feature",id)
00157 ob.Shape = objects[id]
00158 if gui: ob.ViewObject.ShapeColor = color
00159
00160 def parse(filename,doc):
00161 "inports an opened OCA file into the given doc"
00162 filebuffer = pythonopen(filename)
00163 global objects
00164 objects = {}
00165 global color
00166 color = (0,0,0)
00167 for l in filebuffer:
00168 readline = l.replace(","," ").upper()
00169 if ("=" in readline):
00170
00171 pair = readline.split("=")
00172 id = pair[0]
00173 data = pair[1]
00174 data = data.replace(","," ")
00175 data = data.replace("("," ")
00176 data = data.replace(")"," ")
00177 data = data.split()
00178 if id[0] == "P":
00179
00180 objects[id] = getpoint(data)
00181 elif ((id[0] == "A") and params.GetBool("ocaareas")):
00182
00183 objects[id] = getarea(data)
00184 createobject(id,doc)
00185
00186 elif id[0] == "C":
00187
00188 objects[id] = getarc(data)
00189 createobject(id,doc)
00190
00191 elif id[0] == "L":
00192
00193 objects[id] = getline(data)
00194 createobject(id,doc)
00195
00196 elif id[0] == "R":
00197
00198 objects[id] = gettranslation(data)
00199
00200 elif (readline[0:6] == "DEFCOL"):
00201
00202 c = readline.split()
00203 color = (float(c[1])/255,float(c[2])/255,float(c[3])/255)
00204
00205 del color
00206
00207 def decodeName(name):
00208 "decodes encoded strings"
00209 try:
00210 decodedName = (name.decode("utf8"))
00211 except UnicodeDecodeError:
00212 try:
00213 decodedName = (name.decode("latin1"))
00214 except UnicodeDecodeError:
00215 print "oca: error: couldn't determine character encoding"
00216 decodedName = name
00217 return decodedName
00218
00219 def open(filename):
00220 docname=os.path.split(filename)[1]
00221 doc=FreeCAD.newDocument(docname)
00222 if (docname[-4:] == "gcad"): doc.Label = decodeName(docname[:-5])
00223 else: doc.Label = decodeName(docname[:-4])
00224 parse(filename,doc)
00225 doc.recompute()
00226
00227 def insert(filename,docname):
00228 try:
00229 doc=FreeCAD.getDocument(docname)
00230 except:
00231 doc=FreeCAD.newDocument(docname)
00232 parse(filename,doc)
00233 doc.recompute()
00234
00235 def export(exportList,filename):
00236 "called when freecad exports a file"
00237 faces = []
00238 edges = []
00239
00240
00241 for ob in exportList:
00242 if ob.Shape.Faces:
00243 for f in ob.Shape.Faces:
00244 faces.append(f)
00245 else:
00246 for e in ob.Shape.Edges:
00247 edges.append(e)
00248 if not (edges or faces):
00249 print "oca: found no data to export"
00250 return
00251
00252
00253 oca = pythonopen(filename,'wb')
00254 oca.write("#oca file generated from FreeCAD\r\n")
00255 oca.write("# edges\r\n")
00256 count = 1
00257 for e in edges:
00258 if isinstance(e.Curve,Part.Line):
00259 oca.write("L"+str(count)+"=")
00260 oca.write(writepoint(e.Vertexes[0].Point))
00261 oca.write(" ")
00262 oca.write(writepoint(e.Vertexes[-1].Point))
00263 oca.write("\r\n")
00264 elif isinstance(e.Curve,Part.Circle):
00265 if (len(e.Vertexes) > 1):
00266 oca.write("C"+str(count)+"=ARC ")
00267 oca.write(writepoint(e.Vertexes[0].Point))
00268 oca.write(" ")
00269 oca.write(writepoint(fcgeo.findMidpoint(e)))
00270 oca.write(" ")
00271 oca.write(writepoint(e.Vertexes[-1].Point))
00272 else:
00273 oca.write("C"+str(count)+"= ")
00274 oca.write(writepoint(e.Curve.Center))
00275 oca.write(" ")
00276 oca.write(str(e.Curve.Radius))
00277 oca.write("\r\n")
00278 count += 1
00279 oca.write("# faces\r\n")
00280 for f in faces:
00281 oca.write("A"+str(count)+"=S(POL")
00282 for v in f.Vertexes:
00283 oca.write(" ")
00284 oca.write(writepoint(v.Point))
00285 oca.write(" ")
00286 oca.write(writepoint(f.Vertexes[0].Point))
00287 oca.write(")\r\n")
00288 count += 1
00289
00290
00291 oca.close()
00292 FreeCAD.Console.PrintMessage("successfully exported "+filename)
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306