Arch: First version of Sweethome3D importer - issue #2584
This commit is contained in:
parent
4acf8e09dc
commit
3510c71f2b
|
@ -37,6 +37,7 @@ SET(Arch_SRCS
|
|||
ArchProfile.py
|
||||
import3DS.py
|
||||
ArchPrecast.py
|
||||
importSH3D.py
|
||||
)
|
||||
|
||||
SET(Dice3DS_SRCS
|
||||
|
|
|
@ -29,3 +29,4 @@ FreeCAD.addExportType("WebGL file (*.html)","importWebGL")
|
|||
FreeCAD.addImportType("Collada (*.dae)","importDAE")
|
||||
FreeCAD.addExportType("Collada (*.dae)","importDAE")
|
||||
FreeCAD.addImportType("3D Studio mesh (*.3ds)","import3DS")
|
||||
FreeCAD.addImportType("SweetHome3D XML export (*.zip)","importSH3D")
|
||||
|
|
205
src/Mod/Arch/importSH3D.py
Normal file
205
src/Mod/Arch/importSH3D.py
Normal file
|
@ -0,0 +1,205 @@
|
|||
#***************************************************************************
|
||||
#* *
|
||||
#* Copyright (c) 2016 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 SweetHome3D importer"
|
||||
__author__ = "Yorik van Havre"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
import os,zipfile,xml.sax,FreeCAD,Part,Draft,Arch,Mesh,tempfile,math,Sketcher
|
||||
|
||||
DEBUG = True
|
||||
|
||||
if open.__module__ == '__builtin__':
|
||||
pyopen = open # because we'll redefine open below
|
||||
|
||||
|
||||
def open(filename):
|
||||
"called when freecad wants to open a file"
|
||||
docname = (os.path.splitext(os.path.basename(filename))[0]).encode("utf8")
|
||||
doc = FreeCAD.newDocument(docname)
|
||||
doc.Label = decode(docname)
|
||||
FreeCAD.ActiveDocument = doc
|
||||
read(filename)
|
||||
return doc
|
||||
|
||||
|
||||
def insert(filename,docname):
|
||||
"called when freecad wants to import a file"
|
||||
try:
|
||||
doc = FreeCAD.getDocument(docname)
|
||||
except NameError:
|
||||
doc = FreeCAD.newDocument(docname)
|
||||
FreeCAD.ActiveDocument = doc
|
||||
read(filename)
|
||||
return doc
|
||||
|
||||
|
||||
def decode(name):
|
||||
"decodes encoded strings"
|
||||
try:
|
||||
decodedName = (name.decode("utf8"))
|
||||
except UnicodeDecodeError:
|
||||
try:
|
||||
decodedName = (name.decode("latin1"))
|
||||
except UnicodeDecodeError:
|
||||
FreeCAD.Console.PrintError(translate("Arch","Error: Couldn't determine character encoding"))
|
||||
decodedName = name
|
||||
return decodedName
|
||||
|
||||
|
||||
def read(filename):
|
||||
"reads the file and creates objects in the active document"
|
||||
|
||||
z = zipfile.ZipFile(filename)
|
||||
homexml = z.read("Home.xml")
|
||||
handler = SH3DHandler(z)
|
||||
xml.sax.parseString(homexml,handler)
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
if not handler.makeIndividualWalls:
|
||||
delete = []
|
||||
walls = []
|
||||
for k,lines in handler.lines.items():
|
||||
sk = FreeCAD.ActiveDocument.addObject("Sketcher::SketchObject","Walls_trace")
|
||||
for l in lines:
|
||||
for edge in l.Shape.Edges:
|
||||
sk.addGeometry(edge.Curve)
|
||||
delete.append(l.Name)
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
k = k.split(";")
|
||||
walls.append(Arch.makeWall(baseobj=sk,width=float(k[0]),height=float(k[1])))
|
||||
for d in delete:
|
||||
FreeCAD.ActiveDocument.removeObject(d)
|
||||
w = walls.pop()
|
||||
w.Additions = walls
|
||||
w.Subtractions = handler.windows
|
||||
g = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroup","Furniture")
|
||||
g.Group = handler.furniture
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
|
||||
|
||||
class SH3DHandler(xml.sax.ContentHandler):
|
||||
|
||||
def __init__(self,z):
|
||||
|
||||
self.makeIndividualWalls = False
|
||||
self.z = z
|
||||
self.windows = []
|
||||
self.furniture = []
|
||||
self.lines = {}
|
||||
|
||||
def startElement(self, tag, attributes):
|
||||
|
||||
if tag == "wall":
|
||||
name = attributes["id"]
|
||||
p1 = FreeCAD.Vector(float(attributes["xStart"])*10,float(attributes["yStart"])*10,0)
|
||||
p2 = FreeCAD.Vector(float(attributes["xEnd"])*10,float(attributes["yEnd"])*10,0)
|
||||
height = float(attributes["height"])*10
|
||||
thickness = float(attributes["thickness"])*10
|
||||
if DEBUG: print "Creating wall: ",name
|
||||
line = Draft.makeLine(p1,p2)
|
||||
if self.makeIndividualWalls:
|
||||
wall = Arch.makeWall(baseobj=line,width=thickness,height=height,name=name)
|
||||
wall.Label = name
|
||||
else:
|
||||
self.lines.setdefault(str(thickness)+";"+str(height),[]).append(line)
|
||||
|
||||
elif tag == "pieceOfFurniture":
|
||||
name = attributes["name"]
|
||||
data = self.z.read(attributes["model"])
|
||||
tf = tempfile.mkstemp(suffix=".obj")[1]
|
||||
f = pyopen(tf,"wb")
|
||||
f.write(data)
|
||||
f.close()
|
||||
m = Mesh.read(tf)
|
||||
fx = (float(attributes["width"])/100)/m.BoundBox.XLength
|
||||
fy = (float(attributes["height"])/100)/m.BoundBox.YLength
|
||||
fz = (float(attributes["depth"])/100)/m.BoundBox.ZLength
|
||||
mat = FreeCAD.Matrix()
|
||||
mat.scale(1000*fx,1000*fy,1000*fz)
|
||||
mat.rotateX(math.pi/2)
|
||||
mat.rotateZ(math.pi)
|
||||
if DEBUG: print "Creating furniture: ",name
|
||||
if "angle" in attributes.keys():
|
||||
mat.rotateZ(float(attributes["angle"]))
|
||||
m.transform(mat)
|
||||
os.remove(tf)
|
||||
p = m.BoundBox.Center.negative()
|
||||
p = p.add(FreeCAD.Vector(float(attributes["x"])*10,float(attributes["y"])*10,0))
|
||||
p = p.add(FreeCAD.Vector(0,0,m.BoundBox.Center.z-m.BoundBox.ZMin))
|
||||
m.Placement.Base = p
|
||||
obj = FreeCAD.ActiveDocument.addObject("Mesh::Feature",name)
|
||||
obj.Mesh = m
|
||||
self.furniture.append(obj)
|
||||
|
||||
elif tag == "doorOrWindow":
|
||||
name = attributes["name"]
|
||||
data = self.z.read(attributes["model"])
|
||||
tf = tempfile.mkstemp(suffix=".obj")[1]
|
||||
f = pyopen(tf,"wb")
|
||||
f.write(data)
|
||||
f.close()
|
||||
m = Mesh.read(tf)
|
||||
fx = (float(attributes["width"])/100)/m.BoundBox.XLength
|
||||
fy = (float(attributes["height"])/100)/m.BoundBox.YLength
|
||||
fz = (float(attributes["depth"])/100)/m.BoundBox.ZLength
|
||||
mat = FreeCAD.Matrix()
|
||||
mat.scale(1000*fx,1000*fy,1000*fz)
|
||||
mat.rotateX(math.pi/2)
|
||||
m.transform(mat)
|
||||
b = m.BoundBox
|
||||
v1 = FreeCAD.Vector(b.XMin,b.YMin-500,b.ZMin)
|
||||
v2 = FreeCAD.Vector(b.XMax,b.YMin-500,b.ZMin)
|
||||
v3 = FreeCAD.Vector(b.XMax,b.YMax+500,b.ZMin)
|
||||
v4 = FreeCAD.Vector(b.XMin,b.YMax+500,b.ZMin)
|
||||
sub = Part.makePolygon([v1,v2,v3,v4,v1])
|
||||
sub = Part.Face(sub)
|
||||
sub = sub.extrude(FreeCAD.Vector(0,0,b.ZLength))
|
||||
os.remove(tf)
|
||||
shape = Arch.getShapeFromMesh(m)
|
||||
if not shape:
|
||||
shape=Part.Shape()
|
||||
shape.makeShapeFromMesh(m.Topology,0.100000)
|
||||
shape = shape.removeSplitter()
|
||||
if shape:
|
||||
if DEBUG: print "Creating window: ",name
|
||||
if "angle" in attributes.keys():
|
||||
shape.rotate(shape.BoundBox.Center,FreeCAD.Vector(0,0,1),math.degrees(float(attributes["angle"])))
|
||||
sub.rotate(shape.BoundBox.Center,FreeCAD.Vector(0,0,1),math.degrees(float(attributes["angle"])))
|
||||
p = shape.BoundBox.Center.negative()
|
||||
p = p.add(FreeCAD.Vector(float(attributes["x"])*10,float(attributes["y"])*10,0))
|
||||
p = p.add(FreeCAD.Vector(0,0,shape.BoundBox.Center.z-shape.BoundBox.ZMin))
|
||||
if "elevation" in attributes.keys():
|
||||
p = p.add(FreeCAD.Vector(0,0,float(attributes["elevation"])*10))
|
||||
shape.translate(p)
|
||||
sub.translate(p)
|
||||
obj = FreeCAD.ActiveDocument.addObject("Part::Feature",name+"_body")
|
||||
obj.Shape = shape
|
||||
subobj = FreeCAD.ActiveDocument.addObject("Part::Feature",name+"_sub")
|
||||
subobj.Shape = sub
|
||||
if FreeCAD.GuiUp:
|
||||
subobj.ViewObject.hide()
|
||||
win = Arch.makeWindow(baseobj=obj,name=name)
|
||||
win.Label = name
|
||||
win.Subvolume = subobj
|
||||
self.windows.append(win)
|
||||
else:
|
||||
print("importSH3D: Error creating shape for door/window "+name)
|
Loading…
Reference in New Issue
Block a user