Arch: Added SHP importer

This commit is contained in:
Yorik van Havre
2020-05-08 13:00:48 +02:00
parent a6ea85ae99
commit 916a42397c
3 changed files with 171 additions and 0 deletions

View File

@@ -53,6 +53,7 @@ SET(Arch_SRCS
exportIFC.py
ArchTruss.py
ArchCurtainWall.py
importSHP.py
)
SET(Dice3DS_SRCS

View File

@@ -30,3 +30,4 @@ FreeCAD.addImportType("Collada (*.dae)","importDAE")
FreeCAD.addExportType("Collada (*.dae)","importDAE")
FreeCAD.addImportType("3D Studio mesh (*.3ds)","import3DS")
FreeCAD.addImportType("SweetHome3D XML export (*.zip)","importSH3D")
FreeCAD.addImportType("Shapefile (*.shp)","importSHP")

169
src/Mod/Arch/importSHP.py Normal file
View File

@@ -0,0 +1,169 @@
# -*- coding: utf-8 -*-
#***************************************************************************
#* *
#* Copyright (c) 2020 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 *
#* *
#***************************************************************************
from __future__ import print_function
import os
import FreeCAD
import importIFCHelper
translate = FreeCAD.Qt.translate
if open.__module__ in ['__builtin__','io']:
pythonopen = open
def open(filename):
"""opens a SHP/SHX/DBF file in a new FreeCAD document"""
docname = os.path.splitext(os.path.basename(filename))[0]
docname = importIFCHelper.decode(docname,utf=True)
doc = FreeCAD.newDocument(docname)
doc.Label = docname
doc = insert(filename,doc.Name)
return doc
def insert(filename,docname,record=None):
"""imports a SHP/SHX/DBF file in an existing FreeCAD document.
the record attribute is an optional string indicating the shapefile
field to use to give elevations to the different shapes. If not used,
if running in GUI mode, a dialog will pop up to ask the user which
field to use."""
if not checkShapeFileLibrary():
return
import shapefile
import Part
# read the shape file
# doc at https://github.com/GeospatialPython/pyshp
shp = shapefile.Reader(filename)
# check which record to use for elevation
if not record:
fields = ["None"] + [field[0] for field in shp.fields]
if FreeCAD.GuiUp:
import FreeCADGui
from PySide import QtGui
reply = QtGui.QInputDialog.getItem(FreeCADGui.getMainWindow(),
translate("Arch","Shapes elevation"),
translate("Arch","Choose which field provides shapes elevations:"),
fields)
if reply[1]:
if record != "None":
record = reply[0]
# build shapes
shapes = []
for shaperec in shp.shapeRecords():
shape = None
pts = []
for p in shaperec.shape.points:
if len(p) > 2:
pts.append(FreeCAD.Vector(p[0],p[1],p[2]))
else:
pts.append(FreeCAD.Vector(p[0],p[1],0))
if shp.shapeTypeName in ["POLYGON","POLYGONZ"]:
# faces
pts.append(pts[0])
shape = Part.makePolygon(pts)
shape = Part.Face(shape)
elif shp.shapeTypeName in ["POINT","POINTZ"]:
# points
verts = [Part.Vertex(p) for p in pts]
if verts:
shape = Part.makeCompound(verts)
else:
# polylines
shape = Part.makePolygon(pts)
if record:
elev = shaperec.record[record]
if elev:
shape.translate(FreeCAD.Vector(0,0,elev))
if shape:
shapes.append(shape)
if shapes:
result = Part.makeCompound(shapes)
obj = FreeCAD.ActiveDocument.addObject("Part::Feature","shapefile")
obj.Shape = result
obj.Label = os.path.splitext(os.path.basename(filename))[0]
FreeCAD.ActiveDocument.recompute()
else:
FreeCAD.Console.PrintWarning(translate("Arch","No shape found in this file")+"\n")
def getFields(filename):
"""returns the fields found in the given file"""
if not checkShapeFileLibrary():
return
import shapefile
shp = shapefile.Reader(filename)
return [field[0] for field in shp.fields]
def checkShapeFileLibrary():
"""Looks for and/or installs the ShapeFile library"""
try:
import shapefile
except:
url = "https://raw.githubusercontent.com/GeospatialPython/pyshp/master/shapefile.py"
if FreeCAD.GuiUp:
import addonmanager_utilities
import FreeCADGui
from PySide import QtGui
reply = QtGui.QMessageBox.question(FreeCADGui.getMainWindow(),
translate("Arch","Shapefile module not found"),
translate("Arch","The shapefile python library was not found on your system. Would you like to downloadit now from <a href=\"https://github.com/GeospatialPython/pyshp\">https://github.com/GeospatialPython/pyshp</a>? It will be placed in your macros folder."),
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No,
QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
u = addonmanager_utilities.urlopen(url)
if not u:
FreeCAD.Console.PrintError(translate("Arch","Error: Unable to download from:")+" "+url+"\n")
return False
b = u.read()
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macro")
fp = p.GetString("MacroPath",os.path.join(FreeCAD.getUserAppDataDir(),"Macros"))
fp = os.path.join(fp,"shapefile.py")
f = pythonopen(fp,"wb")
f.write(b)
f.close()
try:
import shapefile
except:
FreeCAD.Console.PrintError(translate("Arch","Could not download shapefile module. Aborting.")+"\n")
return False
else:
FreeCAD.Console.PrintError(translate("Arch","Shapefile module not downloaded. Aborting.")+"\n")
return False
else:
FreeCAD.Console.PrintError(translate("Arch","Shapefile module not found. Aborting.")+"\n")
FreeCAD.Console.PrintMessage(translate("Arch","The shapefile library can be downloaded from the following URL and installed in your macros folder:")+"\n")
FreeCAD.Console.PrintMessage(url)
return False
return True