FreeCAD/src/Mod/Draft/importOCA.py

318 lines
11 KiB
Python

# -*- coding: utf8 -*-
#***************************************************************************
#* *
#* Copyright (c) 2009 Yorik van Havre <yorik@uncreated.net> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
__title__="FreeCAD Draft Workbench - OCA importer/exporter"
__author__ = "Yorik van Havre <yorik@uncreated.net>"
__url__ = ["http://www.freecadweb.org"]
## @package importOCA
# \ingroup DRAFT
# \brief OCA (Open CAD Format) file import & export
#
# This module provides support for importing and exporting to the OCA format fron GCAD3D.
# Warning, this file format is today practically obsolete and this module is not
# maintained anymore.
'''
This script imports OCA/gcad files into FreeCAD.
'''
import FreeCAD, os, Part, math, DraftVecUtils, DraftGeomUtils
from FreeCAD import Vector
try: import FreeCADGui
except ValueError: gui = False
else: gui = True
if open.__module__ in ['__builtin__','io']:
pythonopen = open
params = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
def getpoint(data):
"turns an OCA point definition into a FreeCAD Vector"
print("found point ",data)
if (len(data) == 3):
return Vector(float(data[0]),float(data[1]),float(data[2]))
elif (data[0] == "P") and (len(data) == 4):
return Vector(float(data[1]),float(data[2]),float(data[3]))
elif (data[0][0] == "P") and (len(data[0]) > 1):
if (len(data) == 1):
return objects[data[0]]
else:
if (data[1][0] == "R"):
return objects[data[0]].add(objects[data[1]])
elif (data[1][0] == "C"):
return DraftGeomUtils.findProjection(objects[data[0]],objects[data[1]])
elif (data[0][0] == "C"):
if objects[data[0]]:
p1 = objects[data[0]].Curve.Position
if (len(data) == 1):
return p1
else:
if (data[1][0] == "L"):
l = objects[data[1]]
return p1.add(DraftGeomUtils.vec(l))
def getarea(data):
"turns an OCA area definition into a FreeCAD Part Wire"
print("found area ",data)
if (data[0] == "S"):
if (data[1] == "POL"):
pts = data[2:]
verts = []
for p in pts:
if (p[0] == "P"):
verts.append(getpoint([p]))
w = Part.makePolygon(verts)
return w
def getarc(data):
"turns an OCA arc definition into a FreeCAD Part Edge"
print("found arc ", data)
c = None
if (data[0] == "ARC"):
# 3-points arc
pts = data[1:]
verts = []
for p in range(len(pts)):
if (pts[p] == "P"):
verts.append(getpoint(pts[p:p+3]))
elif (pts[p][0] == "P"):
verts.append(getpoint([pts[p]]))
if verts[0] and verts[1] and verts[2]:
c = Part.Arc(verts[0],verts[1],verts[2])
elif (data[0][0] == "P"):
# 2-point circle
verts = []
rad = None
for p in range(len(data)):
if (data[p] == "P"):
verts.append(getpoint(data[p:p+4]))
elif (data[p][0] == "P"):
verts.append(getpoint([data[p]]))
elif (data[p] == "VAL"):
rad = float(data[p+1])
elif (data[p][0] == "L"):
lines.append(objects[data[p]])
c = Part.Circle()
c.Center = verts[0]
if rad: c.Radius = rad
else: c.Radius = DraftVecUtils.new(verts[0],verts[1]).Length
elif (data[0][0] == "L"):
# 2-lines circle
lines = []
rad = None
for p in range(len(data)):
if (data[p] == "VAL"):
rad = float(data[p+1])
elif (data[p][0] == "L"):
lines.append(objects[data[p]])
circles = DraftGeomUtils.circleFrom2LinesRadius(lines[0],lines[1],rad)
if circles: c = circles[0]
if c: return c.toShape()
def getline(data):
print("found line ", data)
"turns an OCA line definition into a FreeCAD Part Edge"
verts = []
for p in range(len(data)):
if (data[p] == "P"):
verts.append(getpoint(data[p:p+4]))
elif (data[p][0] == "P"):
verts.append(getpoint([data[p]]))
l = Part.LineSegment(verts[0],verts[1])
return l.toShape()
def gettranslation(data):
"retrieves a transformation vector"
print("found translation ",data)
if (data[0] == "Z"):
return Vector(0,0,float(data[1]))
elif (data[0] == "Y"):
return Vector(0,float(data[1]),0)
elif (data[0] == "X"):
return Vector(float(data[1]),0,0)
return Vector(0,0,0)
def writepoint(vector):
"writes a FreeCAD vector in OCA format"
return "P("+str(vector.x)+" "+str(vector.y)+" "+str(vector.z)+")"
def createobject(id,doc):
"creates an object in the current document"
if isinstance(objects[id],Part.Shape):
ob = doc.addObject("Part::Feature",id)
ob.Shape = objects[id]
if gui: ob.ViewObject.ShapeColor = color
def parse(filename,doc):
"inports an opened OCA file into the given doc"
filebuffer = pythonopen(filename)
global objects
objects = {}
global color
color = (0,0,0)
for l in filebuffer:
readline = l.replace(","," ").upper()
if ("=" in readline):
# entity definitions
pair = readline.split("=")
id = pair[0]
data = pair[1]
data = data.replace(","," ")
data = data.replace("("," ")
data = data.replace(")"," ")
data = data.split()
if id[0] == "P":
# point
objects[id] = getpoint(data)
elif ((id[0] == "A") and params.GetBool("ocaareas")):
# area
objects[id] = getarea(data)
createobject(id,doc)
elif id[0] == "C":
# arc or circle
objects[id] = getarc(data)
createobject(id,doc)
elif id[0] == "L":
# line
objects[id] = getline(data)
createobject(id,doc)
elif id[0] == "R":
# translation
objects[id] = gettranslation(data)
elif (readline[0:6] == "DEFCOL"):
# color
c = readline.split()
color = (float(c[1])/255,float(c[2])/255,float(c[3])/255)
del color
def decodeName(name):
"decodes encoded strings"
try:
decodedName = (name.decode("utf8"))
except UnicodeDecodeError:
try:
decodedName = (name.decode("latin1"))
except UnicodeDecodeError:
print("oca: error: couldn't determine character encoding")
decodedName = name
return decodedName
def open(filename):
docname=os.path.split(filename)[1]
doc=FreeCAD.newDocument(docname)
if (docname[-4:] == "gcad"): doc.Label = docname[:-5]
else: doc.Label = docname[:-4]
parse(filename,doc)
doc.recompute()
def insert(filename,docname):
try:
doc=FreeCAD.getDocument(docname)
except NameError:
doc=FreeCAD.newDocument(docname)
FreeCAD.ActiveDocument = doc
parse(filename,doc)
doc.recompute()
def export(exportList,filename):
"called when freecad exports a file"
faces = []
edges = []
# getting faces and edges
for ob in exportList:
if ob.Shape.Faces:
for f in ob.Shape.Faces:
faces.append(f)
else:
for e in ob.Shape.Edges:
edges.append(e)
if not (edges or faces):
print("oca: found no data to export")
return
# writing file
oca = pythonopen(filename,'wb')
oca.write("#oca file generated from FreeCAD\r\n")
oca.write("# edges\r\n")
count = 1
for e in edges:
if DraftGeomUtils.geomType(e) == "Line":
oca.write("L"+str(count)+"=")
oca.write(writepoint(e.Vertexes[0].Point))
oca.write(" ")
oca.write(writepoint(e.Vertexes[-1].Point))
oca.write("\r\n")
elif DraftGeomUtils.geomType(e) == "Circle":
if (len(e.Vertexes) > 1):
oca.write("C"+str(count)+"=ARC ")
oca.write(writepoint(e.Vertexes[0].Point))
oca.write(" ")
oca.write(writepoint(DraftGeomUtils.findMidpoint(e)))
oca.write(" ")
oca.write(writepoint(e.Vertexes[-1].Point))
else:
oca.write("C"+str(count)+"= ")
oca.write(writepoint(e.Curve.Center))
oca.write(" ")
oca.write(str(e.Curve.Radius))
oca.write("\r\n")
count += 1
oca.write("# faces\r\n")
for f in faces:
oca.write("A"+str(count)+"=S(POL")
for v in f.Vertexes:
oca.write(" ")
oca.write(writepoint(v.Point))
oca.write(" ")
oca.write(writepoint(f.Vertexes[0].Point))
oca.write(")\r\n")
count += 1
# closing
oca.close()
FreeCAD.Console.PrintMessage("successfully exported "+filename)