Improved SweetHome 3D importer (#17165)
* Fixed access to Addon::Metadat::Url attributes * Fixed invalid vector in distance calculation * SH3D importer initial version * Cleaned up and added baseboard * Make sure notificationWidth is properly enabled/disabled * Added furnitureGroup, color prefs, light weight mesh object * Allow to join walls * Prepare to join wall, improved status feedback * Removing trailing white space * SH3D importer initial version * Cleaned up and added baseboard * Make sure notificationWidth is properly enabled/disabled * Added furnitureGroup, color prefs, light weight mesh object * Allow to join walls * Prepare to join wall, improved status feedback * Removing trailing white space * fixing tipo, 80 charlines, etc * Adding a basic import test * Work in local but fails on pipeline. Commenting out. * Adding testcase and join wall path * Use ruled surface to fix failed sweep * Fixed faces order when joining walls * Fixed missing sample importer file * Allow to change pref just before import * Fixed excessive debug output * Allow to import from string. Test use embedded string * Fixed tipo in comment Co-authored-by: João Matos <joao@tritao.eu> * Improved door import Also added coloring for wall section's edges when debuging * Moved debug init script to FreeCAD-Docker repo --------- Co-authored-by: João Matos <joao@tritao.eu> Co-authored-by: Yorik van Havre <yorik@uncreated.net>
This commit is contained in:
@@ -59,12 +59,14 @@ SET(importers_SRCS
|
||||
importers/importWebGL.py
|
||||
importers/importJSON.py
|
||||
importers/importSH3D.py
|
||||
importers/importSH3DHelper.py
|
||||
importers/import3DS.py
|
||||
importers/importSHP.py
|
||||
importers/importGBXML.py
|
||||
importers/exportIFCStructuralTools.py
|
||||
importers/exportIFC.py
|
||||
importers/exportIFCHelper.py
|
||||
importers/samples/Sample.sh3d
|
||||
)
|
||||
|
||||
SET(Dice3DS_SRCS
|
||||
@@ -198,6 +200,10 @@ SET(BIMGuiIcon_SVG
|
||||
Resources/icons/BIMWorkbench.svg
|
||||
)
|
||||
|
||||
SET(ImportersSample_Files
|
||||
importers/samples/Sample.sh3d
|
||||
)
|
||||
|
||||
ADD_CUSTOM_TARGET(BIM ALL
|
||||
SOURCES ${Arch_SRCS}
|
||||
${Arch_QRC_SRCS}
|
||||
@@ -210,6 +216,10 @@ ADD_CUSTOM_TARGET(BIM ALL
|
||||
${BIMGuiIcon_SVG}
|
||||
)
|
||||
|
||||
ADD_CUSTOM_TARGET(ImporterPythonTestData ALL
|
||||
SOURCES ${ImportersSample_Files}
|
||||
)
|
||||
|
||||
fc_copy_sources(BIM "${CMAKE_BINARY_DIR}/Mod/BIM" ${Arch_SRCS})
|
||||
fc_copy_sources(BIM "${CMAKE_BINARY_DIR}/Mod/BIM" ${Dice3DS_SRCS})
|
||||
fc_copy_sources(BIM "${CMAKE_BINARY_DIR}/Mod/BIM" ${importers_SRCS})
|
||||
@@ -223,6 +233,12 @@ fc_target_copy_resource(BIM
|
||||
${Arch_presets}
|
||||
)
|
||||
|
||||
fc_target_copy_resource(ImporterPythonTestData
|
||||
${CMAKE_SOURCE_DIR}/src/Mod/BIM
|
||||
${CMAKE_BINARY_DIR}/Mod/BIM
|
||||
${ImportersSample_Files})
|
||||
|
||||
|
||||
IF (BUILD_GUI)
|
||||
fc_target_copy_resource(BIM
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
|
||||
@@ -33,5 +33,5 @@ FreeCAD.addExportType("JavaScript Object Notation (*.json)","importers.importJSO
|
||||
FreeCAD.addImportType("Collada (*.dae *.DAE)","importers.importDAE")
|
||||
FreeCAD.addExportType("Collada (*.dae)","importers.importDAE")
|
||||
FreeCAD.addImportType("3D Studio mesh (*.3ds *.3DS)","importers.import3DS")
|
||||
FreeCAD.addImportType("SweetHome3D XML export (*.zip *.ZIP)","importers.importSH3D")
|
||||
FreeCAD.addImportType("SweetHome3D (*.sh3d)","importers.importSH3D")
|
||||
FreeCAD.addImportType("Shapefile (*.shp *.SHP)","importers.importSHP")
|
||||
|
||||
@@ -677,6 +677,7 @@ t = QT_TRANSLATE_NOOP("QObject", "Import-Export")
|
||||
FreeCADGui.addPreferencePage(":/ui/preferences-ifc.ui", t)
|
||||
FreeCADGui.addPreferencePage(":/ui/preferences-ifc-export.ui", t)
|
||||
FreeCADGui.addPreferencePage(":/ui/preferences-dae.ui", t)
|
||||
FreeCADGui.addPreferencePage(":/ui/preferences-sh3d-import.ui", t)
|
||||
|
||||
# Add unit tests
|
||||
FreeCAD.__unit_test__ += ["TestArch"]
|
||||
|
||||
@@ -268,6 +268,7 @@
|
||||
<file>ui/preferences-dae.ui</file>
|
||||
<file>ui/preferences-ifc-export.ui</file>
|
||||
<file>ui/preferences-ifc.ui</file>
|
||||
<file>ui/preferences-sh3d-import.ui</file>
|
||||
<file>ui/preferencesNativeIFC.ui</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
337
src/Mod/BIM/Resources/ui/preferences-sh3d-import.ui
Normal file
337
src/Mod/BIM/Resources/ui/preferences-sh3d-import.ui
Normal file
@@ -0,0 +1,337 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Gui::Dialog::DlgSettingsArch</class>
|
||||
<widget class="QWidget" name="Gui::Dialog::DlgSettingsArch">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>555</width>
|
||||
<height>729</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>SH3D import</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string>General options</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="Gui::PrefCheckBox" name="checkBox_1">
|
||||
<property name="text">
|
||||
<string>Show this dialog when importing</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>sh3dShowDialog</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Arch</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Gui::PrefCheckBox" name="checkBox_2">
|
||||
<property name="toolTip">
|
||||
<string>Shows verbose debug messages during import of SH3D files in the Report
|
||||
view panel. Log level message must be allowed for this setting to have an effect.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show debug messages</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>sh3dDebug</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Arch</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Import options</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="Gui::PrefCheckBox" name="checkBox_3">
|
||||
<property name="toolTip">
|
||||
<string>Whether to import the model's doors and windows</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Doors and Windows</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>sh3dImportDoorsAndWindows</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Arch</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Gui::PrefCheckBox" name="checkBox_4">
|
||||
<property name="toolTip">
|
||||
<string>Whether to import the model's furnitures</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Furnitures</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>sh3dImportFurnitures</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Arch</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Gui::PrefCheckBox" name="checkBox_5">
|
||||
<property name="toolTip">
|
||||
<string>Whether to create Arch::Equipment for each furniture defined in the model (NOTE: this can negatively impact the import process speed)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Create Arch::Equipment</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>sh3dCreateArchEquipment</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Arch</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Gui::PrefCheckBox" name="checkBox_6">
|
||||
<property name="toolTip">
|
||||
<string>Whether to join the different Arch::Wall together</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Join Arch::Wall</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>sh3dJoinArchWall</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Arch</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Gui::PrefCheckBox" name="checkBox_7">
|
||||
<property name="toolTip">
|
||||
<string>Whether to import the model's lights. Note that you also need to import
|
||||
the model's furnitures.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Lights (requires Render)</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>sh3dImportLights</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Arch</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Gui::PrefCheckBox" name="checkBox_8">
|
||||
<property name="toolTip">
|
||||
<string>Whether to import the model's cameras</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Cameras (requires Render)</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>sh3dImportCameras</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Arch</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Gui::PrefCheckBox" name="checkBox_9">
|
||||
<property name="toolTip">
|
||||
<string>Merge imported element with existing FC object</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Merge into existing document</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>sh3dMerge</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Arch</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" columnstretch="2,1,0">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label1">
|
||||
<property name="text">
|
||||
<string>Default Floor Color</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>sh3dDefaultFloorColor</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="Gui::PrefColorButton" name="ArchSH3DDefaultFloorColor">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>This color might be used when a room does not define its own color.</string>
|
||||
</property>
|
||||
<property name="color" stdset="0">
|
||||
<color>
|
||||
<red>150</red>
|
||||
<green>169</green>
|
||||
<blue>186</blue>
|
||||
</color>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>sh3dDefaultFloorColor</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Arch</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" columnstretch="2,1,0">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label1">
|
||||
<property name="text">
|
||||
<string>Default Ceiling Color</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>sh3dDefaultCeilingColor</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="Gui::PrefColorButton" name="ArchSH3DDefaultCeilingColor">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>This color might be used when a room does not define its own color.</string>
|
||||
</property>
|
||||
<property name="color" stdset="0">
|
||||
<color>
|
||||
<red>255</red>
|
||||
<green>255</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>sh3dDefaultCeilingColor</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Arch</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Gui::PrefCheckBox" name="checkBox_10">
|
||||
<property name="toolTip">
|
||||
<string>Create a default Render project with the newly Site</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Create Render Project (requires Render)</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>sh3dCreateRenderProject</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Arch</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Gui::PrefCheckBox" name="checkBox_11">
|
||||
<property name="toolTip">
|
||||
<string>Fit view while importing.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Fit view while importing</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>sh3dFitView</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Arch</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11" />
|
||||
<pixmapfunction>qPixmapFromMimeSource</pixmapfunction>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Gui::PrefSpinBox</class>
|
||||
<extends>QSpinBox</extends>
|
||||
<header>Gui/PrefWidgets.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Gui::PrefCheckBox</class>
|
||||
<extends>QCheckBox</extends>
|
||||
<header>Gui/PrefWidgets.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Gui::PrefComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>Gui/PrefWidgets.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Gui::PrefLineEdit</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>Gui/PrefWidgets.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources />
|
||||
<connections />
|
||||
</ui>
|
||||
@@ -759,6 +759,20 @@ class ArchTest(unittest.TestCase):
|
||||
App.ActiveDocument.recompute()
|
||||
assert wall.Visibility
|
||||
|
||||
def testImportSH3D(self):
|
||||
"""Import a SweetHome 3D file
|
||||
"""
|
||||
operation = "importers.importSH3D"
|
||||
_msg(" Test '{}'".format(operation))
|
||||
import BIM.importers.importSH3DHelper
|
||||
importer = BIM.importers.importSH3DHelper.SH3DImporter(None)
|
||||
importer.import_sh3d_from_string(SH3D_HOME)
|
||||
assert App.ActiveDocument.Project
|
||||
assert App.ActiveDocument.Site
|
||||
assert App.ActiveDocument.BuildingPart.Label == "Building"
|
||||
assert App.ActiveDocument.BuildingPart001.Label == "Level"
|
||||
assert App.ActiveDocument.Wall
|
||||
|
||||
def testViewGeneration(self):
|
||||
"""Tests the whole TD view generation workflow"""
|
||||
|
||||
@@ -804,8 +818,77 @@ class ArchTest(unittest.TestCase):
|
||||
view.Y = "15cm"
|
||||
App.ActiveDocument.recompute()
|
||||
assert True
|
||||
|
||||
|
||||
def tearDown(self):
|
||||
App.closeDocument("ArchTest")
|
||||
pass
|
||||
|
||||
|
||||
SH3D_HOME = """<?xml version='1.0'?>
|
||||
<home version='7200' name='0-JoinWall.sh3d' camera='topCamera' wallHeight='250.0'>
|
||||
<property name='com.eteks.sweethome3d.SweetHome3D.CatalogPaneDividerLocation' value='327'/>
|
||||
<property name='com.eteks.sweethome3d.SweetHome3D.ColumnWidths' value='100,84,82,85,84'/>
|
||||
<property name='com.eteks.sweethome3d.SweetHome3D.FrameHeight' value='576'/>
|
||||
<property name='com.eteks.sweethome3d.SweetHome3D.FrameMaximized' value='true'/>
|
||||
<property name='com.eteks.sweethome3d.SweetHome3D.FrameWidth' value='1092'/>
|
||||
<property name='com.eteks.sweethome3d.SweetHome3D.FrameX' value='50'/>
|
||||
<property name='com.eteks.sweethome3d.SweetHome3D.FrameY' value='87'/>
|
||||
<property name='com.eteks.sweethome3d.SweetHome3D.MainPaneDividerLocation' value='441'/>
|
||||
<property name='com.eteks.sweethome3d.SweetHome3D.PlanPaneDividerLocation' value='263'/>
|
||||
<property name='com.eteks.sweethome3d.SweetHome3D.PlanScale' value='0.21343713'/>
|
||||
<property name='com.eteks.sweethome3d.SweetHome3D.PlanViewportX' value='0'/>
|
||||
<property name='com.eteks.sweethome3d.SweetHome3D.PlanViewportY' value='0'/>
|
||||
<property name='com.eteks.sweethome3d.SweetHome3D.ScreenHeight' value='720'/>
|
||||
<property name='com.eteks.sweethome3d.SweetHome3D.ScreenWidth' value='1366'/>
|
||||
<furnitureVisibleProperty name='NAME'/>
|
||||
<furnitureVisibleProperty name='WIDTH'/>
|
||||
<furnitureVisibleProperty name='DEPTH'/>
|
||||
<furnitureVisibleProperty name='HEIGHT'/>
|
||||
<furnitureVisibleProperty name='VISIBLE'/>
|
||||
<environment groundColor='FFB78744' skyColor='00CCE4FC' lightColor='00D0D0D0' ceillingLightColor='00D0D0D0' photoWidth='400' photoHeight='300' photoAspectRatio='VIEW_3D_RATIO' photoQuality='0' videoWidth='320' videoAspectRatio='RATIO_4_3' videoQuality='0' videoFrameRate='25'>
|
||||
<texture attribute='skyTexture' name='Cloudy' creator='eTeks' catalogId='eTeks#cloudy' width='100.0' height='27.6' image='0'/>
|
||||
</environment>
|
||||
<compass x='-100.0' y='50.0' diameter='100.0' northDirection='0.0' longitude='-0.06428629' latitude='0.70511305' timeZone='Europe/Madrid'/>
|
||||
<observerCamera attribute='observerCamera' lens='PINHOLE' x='50.0' y='50.0' z='170.0' yaw='5.4977875' pitch='0.19634955' fieldOfView='1.0995575' time='1729080000000'/>
|
||||
<camera attribute='topCamera' lens='PINHOLE' x='1304.082' y='1936.5889' z='1526.6199' yaw='8.98363' pitch='0.7049999' fieldOfView='1.0995575' time='1729080000000'/>
|
||||
<wall id='wall0' wallAtEnd='wall1' xStart='0.0' yStart='0.0' xEnd='100.0' yEnd='0.0' height='250.0' thickness='10.0' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall1' wallAtStart='wall0' wallAtEnd='wall2' xStart='100.0' yStart='0.0' xEnd='200.0' yEnd='0.0' height='250.0' thickness='10.0' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall2' wallAtStart='wall1' xStart='200.0' yStart='0.0' xEnd='300.0' yEnd='0.0' height='250.0' thickness='10.0' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall3' wallAtEnd='wall4' xStart='0.0' yStart='50.0' xEnd='100.0' yEnd='100.0' height='250.0' thickness='10.0' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall4' wallAtStart='wall3' wallAtEnd='wall5' xStart='100.0' yStart='100.0' xEnd='200.0' yEnd='100.0' height='250.0' thickness='10.0' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall5' wallAtStart='wall4' xStart='200.0' yStart='100.0' xEnd='300.0' yEnd='50.0' height='250.0' thickness='10.0' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall6' wallAtEnd='wall7' xStart='0.0' yStart='200.0' xEnd='100.0' yEnd='300.0' height='250.0' thickness='10.0' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall7' wallAtStart='wall6' wallAtEnd='wall8' xStart='100.0' yStart='300.0' xEnd='200.0' yEnd='300.0' height='250.0' thickness='10.0' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall8' wallAtStart='wall7' xStart='200.0' yStart='300.0' xEnd='300.0' yEnd='200.0' height='250.0' thickness='10.0' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall9' wallAtEnd='wall10' xStart='100.0' yStart='400.0' xEnd='100.0' yEnd='500.0' height='250.0' thickness='10.0' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall10' wallAtStart='wall9' wallAtEnd='wall11' xStart='100.0' yStart='500.0' xEnd='200.0' yEnd='500.0' height='250.0' thickness='10.0' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall11' wallAtStart='wall10' xStart='200.0' yStart='500.0' xEnd='200.0' yEnd='400.0' height='250.0' thickness='10.0' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall12' wallAtStart='wall14' wallAtEnd='wall13' xStart='150.0' yStart='600.0' xEnd='100.0' yEnd='700.0' height='250.0' thickness='10.0' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall13' wallAtStart='wall12' wallAtEnd='wall14' xStart='100.0' yStart='700.0' xEnd='200.0' yEnd='700.0' height='250.0' thickness='10.0' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall14' wallAtStart='wall13' wallAtEnd='wall12' xStart='200.0' yStart='700.0' xEnd='150.0' yEnd='600.0' height='250.0' thickness='10.0' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall15' wallAtEnd='wall16' xStart='400.0' yStart='150.0' xEnd='500.0' yEnd='100.0' height='250.0' thickness='10.0' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall16' wallAtStart='wall15' wallAtEnd='wall17' xStart='500.0' yStart='100.0' xEnd='600.0' yEnd='100.0' height='250.0' thickness='10.0' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall17' wallAtStart='wall16' xStart='600.0' yStart='100.0' xEnd='700.0' yEnd='50.0' height='250.0' thickness='10.0' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall18' wallAtEnd='wall19' xStart='400.0' yStart='400.0' xEnd='500.0' yEnd='300.0' height='250.0' thickness='10.0' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall19' wallAtStart='wall18' wallAtEnd='wall20' xStart='500.0' yStart='300.0' xEnd='600.0' yEnd='300.0' height='250.0' thickness='10.0' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall20' wallAtStart='wall19' xStart='600.0' yStart='300.0' xEnd='700.0' yEnd='200.0' height='250.0' thickness='10.0' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall21' wallAtEnd='wall22' xStart='400.0' yStart='600.0' xEnd='400.0' yEnd='500.0' height='250.0' thickness='10.0' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall22' wallAtStart='wall21' wallAtEnd='wall23' xStart='400.0' yStart='500.0' xEnd='600.0' yEnd='500.0' height='250.0' thickness='10.0' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall23' wallAtStart='wall22' xStart='600.0' yStart='500.0' xEnd='600.0' yEnd='400.0' height='250.0' thickness='10.0' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall24' wallAtEnd='wall25' xStart='600.0' yStart='800.0' xEnd='500.0' yEnd='700.0' height='250.0' thickness='10.0' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall25' wallAtStart='wall24' wallAtEnd='wall26' xStart='500.0' yStart='700.0' xEnd='600.0' yEnd='700.0' height='250.0' thickness='10.0' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall26' wallAtStart='wall25' xStart='600.0' yStart='700.0' xEnd='500.0' yEnd='600.0' height='250.0' thickness='10.0' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall27' wallAtStart='wall30' wallAtEnd='wall28' xStart='800.0' yStart='0.0' xEnd='1000.0' yEnd='0.0' height='250.0' thickness='10.0' arcExtent='1.0471976' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall28' wallAtStart='wall27' wallAtEnd='wall29' xStart='1000.0' yStart='0.0' xEnd='1000.0' yEnd='100.0' height='250.0' thickness='10.0' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall29' wallAtStart='wall28' wallAtEnd='wall30' xStart='1000.0' yStart='100.0' xEnd='800.0' yEnd='100.0' height='250.0' thickness='10.0' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall30' wallAtStart='wall29' wallAtEnd='wall27' xStart='800.0' yStart='100.0' xEnd='800.0' yEnd='0.0' height='250.0' thickness='10.0' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall31' wallAtEnd='wall32' xStart='800.0' yStart='400.0' xEnd='1000.0' yEnd='200.0' height='250.0' thickness='10.0' arcExtent='1.5707964' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall32' wallAtStart='wall31' wallAtEnd='wall33' xStart='1000.0' yStart='200.0' xEnd='1200.0' yEnd='400.0' height='250.0' thickness='10.0' arcExtent='1.5707964' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall33' wallAtStart='wall32' wallAtEnd='wall34' xStart='1200.0' yStart='400.0' xEnd='1000.0' yEnd='600.0' height='250.0' thickness='10.0' arcExtent='1.5707964' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall34' wallAtStart='wall33' xStart='1000.0' yStart='600.0' xEnd='800.0' yEnd='400.0' height='250.0' thickness='10.0' arcExtent='1.5707964' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall35' wallAtEnd='wall36' xStart='800.0' yStart='800.0' xEnd='900.0' yEnd='900.0' height='250.0' thickness='10.0' arcExtent='-3.1415927' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall36' wallAtStart='wall35' wallAtEnd='wall37' xStart='900.0' yStart='900.0' xEnd='1000.0' yEnd='800.0' height='250.0' thickness='10.0' arcExtent='-3.1415927' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall37' wallAtStart='wall36' wallAtEnd='wall38' xStart='1000.0' yStart='800.0' xEnd='900.0' yEnd='700.0' height='250.0' thickness='10.0' arcExtent='-3.1415927' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
<wall id='wall38' wallAtStart='wall37' xStart='900.0' yStart='700.0' xEnd='800.0' yEnd='800.0' height='250.0' thickness='10.0' arcExtent='-3.1415927' pattern='hatchUp' topColor='FF0000FF' leftSideColor='FF00FF00' rightSideColor='FFFF0000'/>
|
||||
</home>
|
||||
"""
|
||||
|
||||
@@ -23,18 +23,13 @@ __title__ = "FreeCAD SweetHome3D Importer"
|
||||
__author__ = "Yorik van Havre"
|
||||
__url__ = "https://www.freecad.org"
|
||||
|
||||
import math
|
||||
import os
|
||||
import tempfile
|
||||
import xml.sax
|
||||
import zipfile
|
||||
from builtins import open as pyopen
|
||||
|
||||
import FreeCAD
|
||||
import Arch
|
||||
import Draft
|
||||
import Mesh
|
||||
import Part
|
||||
from FreeCAD import Base
|
||||
|
||||
|
||||
## @package importSH3D
|
||||
# \ingroup ARCH
|
||||
@@ -69,140 +64,16 @@ def insert(filename,docname):
|
||||
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)
|
||||
import BIM.importers.importSH3DHelper
|
||||
if DEBUG:
|
||||
from importlib import reload
|
||||
reload(BIM.importers.importSH3DHelper)
|
||||
|
||||
pi = Base.ProgressIndicator()
|
||||
try:
|
||||
importer = BIM.importers.importSH3DHelper.SH3DImporter(pi)
|
||||
importer.import_sh3d_from_filename(filename)
|
||||
finally:
|
||||
pi.stop()
|
||||
|
||||
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):
|
||||
|
||||
super().__init__()
|
||||
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"])
|
||||
th,tf = tempfile.mkstemp(suffix=".obj")
|
||||
f = pyopen(tf,"wb")
|
||||
f.write(data)
|
||||
f.close()
|
||||
os.close(th)
|
||||
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:
|
||||
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"])
|
||||
th,tf = tempfile.mkstemp(suffix=".obj")
|
||||
f = pyopen(tf,"wb")
|
||||
f.write(data)
|
||||
f.close()
|
||||
os.close(th)
|
||||
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:
|
||||
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:
|
||||
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)
|
||||
|
||||
1711
src/Mod/BIM/importers/importSH3DHelper.py
Normal file
1711
src/Mod/BIM/importers/importSH3DHelper.py
Normal file
File diff suppressed because it is too large
Load Diff
BIN
src/Mod/BIM/importers/samples/Sample.sh3d
Normal file
BIN
src/Mod/BIM/importers/samples/Sample.sh3d
Normal file
Binary file not shown.
@@ -43,7 +43,23 @@ Part = lz.LazyLoader("Part", globals(), "Part")
|
||||
|
||||
|
||||
def isClockwise(edge, ref=None):
|
||||
"""Return True if a circle-based edge has a clockwise direction."""
|
||||
"""Return True if a circle-based edge has a clockwise direction.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
edge :
|
||||
The edge to be analyzed.
|
||||
|
||||
ref : Vector, optional
|
||||
The normal around which the direction of the edge is to be determined.
|
||||
Defaults to the Z normal vector.
|
||||
|
||||
Returns
|
||||
-------
|
||||
bool
|
||||
Returns True if the edge is clockwise oriented around the ref Vector
|
||||
or not.
|
||||
"""
|
||||
if not geomType(edge) == "Circle":
|
||||
return True
|
||||
|
||||
|
||||
@@ -242,7 +242,18 @@ def hasOnlyWires(shape):
|
||||
|
||||
|
||||
def geomType(edge):
|
||||
"""Return the type of geometry this edge is based on."""
|
||||
"""Return the type of geometry this edge is based on.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
edge: the edge whose `Curve` attribute is to be checked.
|
||||
|
||||
Returns
|
||||
-------
|
||||
str
|
||||
Return the type of the edge's Curve attribute or "Unknown",
|
||||
if the parameter is missing.
|
||||
"""
|
||||
try:
|
||||
if isinstance(edge.Curve, (Part.LineSegment, Part.Line)):
|
||||
return "Line"
|
||||
|
||||
@@ -49,8 +49,43 @@ def findIntersection(edge1, edge2,
|
||||
|
||||
You can also feed 4 points instead of `edge1` and `edge2`.
|
||||
If `dts` is used, `Shape.section()` is used.
|
||||
"""
|
||||
|
||||
Parameters
|
||||
----------
|
||||
edge1
|
||||
Part.Edge, Circle, Line -> the first edge.
|
||||
Base::Vector3 -> the starting point of the first line. In which case
|
||||
`infinite1` must also be a point.
|
||||
edge2
|
||||
Part.Edge, Circle, Line -> the second edge.
|
||||
Base::Vector3 -> the ending point of the second line. In which case
|
||||
`infinite2` must also be a point.
|
||||
the second edge. In case of a point, `infinite2` must also be a point.
|
||||
infinite1
|
||||
bool, optional -> whether `edge1` should be continued to infinity.
|
||||
Default to `False`.
|
||||
Base::Vector3 -> if `edge1` is a point, must also be a point.
|
||||
infinite2
|
||||
bool, optional -> whether `edge2` should be continued to infinity.
|
||||
Default to `False`.
|
||||
Base::Vector3 -> if `edge2` is a point, must also be a point.
|
||||
ex1: bool, optional
|
||||
In case `edge1` is a point, indicate whether the line should be
|
||||
continued to infinity. Default to `False`
|
||||
ex2: bool, optional
|
||||
In case `edge2` is a point, indicate whether the line should be
|
||||
continued to infinity. Default to `False`
|
||||
dts: bool, optional
|
||||
NOT_DOCUMENTED. Default to `True`
|
||||
findAll: bool, optional
|
||||
In case either `edge1` or `edge2` is a circle, indicates whether
|
||||
to find all intersection points. Default to `False`
|
||||
|
||||
Returns
|
||||
-------
|
||||
list
|
||||
A list of intersection points
|
||||
"""
|
||||
def getLineIntersections(pt1, pt2, pt3, pt4, infinite1, infinite2):
|
||||
if pt1:
|
||||
# first check if we don't already have coincident endpoints
|
||||
|
||||
@@ -135,6 +135,21 @@ def offset(edge, vector, trim=False):
|
||||
and a complete circle will be returned.
|
||||
|
||||
None if there is a problem.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
edge: Part.Shape
|
||||
the edge to offset
|
||||
vector: Base::Vector3
|
||||
the vector by which the edge is to be offset
|
||||
trim: bool, optional
|
||||
If `edge` is an arc and `trim` is `True`, the resulting
|
||||
arc will be trimmed to the proper angle
|
||||
|
||||
Returns
|
||||
-------
|
||||
Part.Shape
|
||||
The offset shape
|
||||
"""
|
||||
if (not isinstance(edge, Part.Shape)
|
||||
or not isinstance(vector, App.Vector)):
|
||||
|
||||
@@ -538,7 +538,8 @@ def _get_param_dictionary():
|
||||
":/ui/preferences-archdefaults.ui",
|
||||
":/ui/preferences-dae.ui",
|
||||
":/ui/preferences-ifc.ui",
|
||||
":/ui/preferences-ifc-export.ui"):
|
||||
":/ui/preferences-ifc-export.ui",
|
||||
":/ui/preferences-sh3d-import.ui",):
|
||||
|
||||
# https://stackoverflow.com/questions/14750997/load-txt-file-from-resources-in-python
|
||||
fd = QtCore.QFile(fnm)
|
||||
|
||||
Reference in New Issue
Block a user