Files
create/src/Mod/BIM/Arch.py

1707 lines
57 KiB
Python

# SPDX-License-Identifier: LGPL-2.1-or-later
# ***************************************************************************
# * *
# * Copyright (c) 2011 Yorik van Havre <yorik@uncreated.net> *
# * *
# * This file is part of FreeCAD. *
# * *
# * FreeCAD is free software: you can redistribute it and/or modify it *
# * under the terms of the GNU Lesser General Public License as *
# * published by the Free Software Foundation, either version 2.1 of the *
# * License, or (at your option) any later version. *
# * *
# * FreeCAD 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 *
# * Lesser General Public License for more details. *
# * *
# * You should have received a copy of the GNU Lesser General Public *
# * License along with FreeCAD. If not, see *
# * <https://www.gnu.org/licenses/>. *
# * *
# ***************************************************************************
__title__ = "FreeCAD Arch API"
__author__ = "Yorik van Havre"
__url__ = "https://www.freecad.org"
## \defgroup ARCH Arch
# \ingroup PYTHONWORKBENCHES
# \brief Architecture and BIM tools
#
# This module provides tools specialized in Building Information Modeling (BIM).
# such as convenience tools to build walls, windows or structures, and
# IFC import/export capabilities.
'''The Arch module provides tools specialized in BIM modeling.'''
import FreeCAD
if FreeCAD.GuiUp:
import FreeCADGui
FreeCADGui.updateLocale()
QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP
translate = FreeCAD.Qt.translate
# generic functions
from ArchCommands import *
from ArchWindowPresets import *
# TODO: migrate this one
from ArchStructure import *
# make functions
def makeAxis(num=1, size=1000, name=None):
"""
Creates an axis set in the active document.
Parameters
----------
num : int, optional
The number of axes to create. Defaults to 1.
size : float, optional
The interval distance between axes. Defaults to 1000.
name : str, optional
The name to assign to the created axis object. Defaults to None.
Returns
-------
Part::FeaturePython
The created axis object.
"""
import ArchAxis
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
return
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "Axis")
obj.Label = name if name else translate("Arch", "Axes")
ArchAxis._Axis(obj)
if FreeCAD.GuiUp:
ArchAxis._ViewProviderAxis(obj.ViewObject)
if num:
dist = []
angles = []
for i in range(num):
if i == 0:
dist.append(0)
else:
dist.append(float(size))
angles.append(float(0))
obj.Distances = dist
obj.Angles = angles
FreeCAD.ActiveDocument.recompute()
return obj
def makeAxisSystem(axes, name=None):
"""
Creates an axis system from the given list of axes.
Parameters
----------
axes : list of Part::FeaturePython
A list of axis objects to include in the axis system.
name : str, optional
The name to assign to the created axis system. Defaults to None.
Returns
-------
App::FeaturePython
The created axis system object.
"""
import ArchAxisSystem
if not isinstance(axes, list):
axes = [axes]
obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython", "AxisSystem")
obj.Label = name if name else translate("Arch", "Axis System")
ArchAxisSystem._AxisSystem(obj)
obj.Axes = axes
if FreeCAD.GuiUp:
ArchAxisSystem._ViewProviderAxisSystem(obj.ViewObject)
FreeCAD.ActiveDocument.recompute()
return obj
def makeBuildingPart(objectslist=None, baseobj=None, name=None):
"""
Creates a building part including the given objects in the list.
Parameters
----------
objectslist : list of Part::FeaturePython, optional
A list of objects to include in the building part. Defaults to None.
baseobj : Part::FeaturePython, optional
The base object for the building part. Defaults to None.
name : str, optional
The name to assign to the created building part. Defaults to None.
Returns
-------
App::GeometryPython
The created building part object.
"""
import ArchBuildingPart
obj = FreeCAD.ActiveDocument.addObject("App::GeometryPython", "BuildingPart")
#obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython","BuildingPart")
obj.Label = name if name else translate("Arch", "BuildingPart")
ArchBuildingPart.BuildingPart(obj)
obj.IfcType = "Building Element Part"
if FreeCAD.GuiUp:
ArchBuildingPart.ViewProviderBuildingPart(obj.ViewObject)
if objectslist:
if isinstance(objectslist, (list, tuple)):
obj.addObjects(objectslist)
else:
obj.addObject(objectslist)
return obj
def makeFloor(objectslist=None, baseobj=None, name=None):
"""
Creates a floor/level in the active document.
Parameters
----------
objectslist : list of Part::FeaturePython, optional
A list of objects to include in the floor. Defaults to None.
baseobj : Part::FeaturePython, optional
The base object for the floor. Defaults to None.
name : str, optional
The name to assign to the created floor. Defaults to None.
Returns
-------
App::GeometryPython
The created floor object.
"""
obj = makeBuildingPart(objectslist)
obj.Label = name if name else translate("Arch", "Level")
obj.IfcType = "Building Storey"
obj.CompositionType = "ELEMENT"
return obj
def makeBuilding(objectslist=None, baseobj=None, name=None):
"""
Creates a building in the active document.
Parameters
----------
objectslist : list of Part::FeaturePython, optional
A list of objects to include in the building. Defaults to None.
baseobj : Part::FeaturePython, optional
The base object for the building. Defaults to None.
name : str, optional
The name to assign to the created building. Defaults to None.
Returns
-------
App::GeometryPython
The created building object.
"""
import ArchBuildingPart
obj = makeBuildingPart(objectslist)
obj.Label = name if name else translate("Arch", "Building")
obj.IfcType = "Building"
obj.CompositionType = "ELEMENT"
t = QT_TRANSLATE_NOOP("App::Property", "The type of this building")
obj.addProperty("App::PropertyEnumeration", "BuildingType", "Building", t, locked=True)
obj.BuildingType = ArchBuildingPart.BuildingTypes
if FreeCAD.GuiUp:
obj.ViewObject.ShowLevel = False
obj.ViewObject.ShowLabel = False
return obj
def make2DDrawing(objectslist=None, baseobj=None, name=None):
"""
Creates a 2D drawing view in the active document.
Parameters
----------
objectslist : list of Part::FeaturePython, optional
A list of objects to include in the drawing. Defaults to None.
baseobj : Part::FeaturePython, optional
The base object for the drawing. Defaults to None.
name : str, optional
The name to assign to the created drawing. Defaults to None.
Returns
-------
App::GeometryPython
The created 2D drawing object.
"""
obj = makeBuildingPart(objectslist)
obj.Label = name if name else translate("Arch", "Drawing")
obj.IfcType = "Annotation"
obj.ObjectType = "DRAWING"
obj.setEditorMode("Area", 2)
obj.setEditorMode("Height", 2)
obj.setEditorMode("LevelOffset", 2)
obj.setEditorMode("OnlySolids", 2)
obj.setEditorMode("HeightPropagate", 2)
if FreeCAD.GuiUp:
obj.ViewObject.DisplayOffset = FreeCAD.Placement()
obj.ViewObject.ShowLevel = False
return obj
def convertFloors(floor=None):
"""
Converts the given floor or building into building parts.
Parameters
----------
floor : Part::FeaturePython, optional
The floor or building to convert. If None, all Arch floors in the active document
are converted. Defaults to None.
Returns
-------
None
"""
import Draft
import ArchBuildingPart
todel = []
if floor:
objset = [floor]
else:
objset = FreeCAD.ActiveDocument.Objects
for obj in objset:
if Draft.getType(obj) in ["Floor", "Building"]:
nobj = makeBuildingPart(obj.Group)
if Draft.getType(obj) == "Floor":
nobj.IfcType = "Building Storey"
nobj.CompositionType = "ELEMENT"
else:
nobj.IfcType = "Building"
nobj.CompositionType = "ELEMENT"
t = QT_TRANSLATE_NOOP("App::Property", "The type of this building")
nobj.addProperty("App::PropertyEnumeration", "BuildingType", "Building", t, locked=True)
nobj.BuildingType = ArchBuildingPart.BuildingTypes
label = obj.Label
for parent in obj.InList:
if hasattr(parent, "Group"):
if obj in parent.Group:
parent.addObject(nobj)
#g = parent.Group
#g.append(nobj)
#parent.Group = g
todel.append(obj.Name)
if obj.ViewObject:
# some bug makes this trigger even efter the object has been deleted...
obj.ViewObject.Proxy.Object = None
# in case FreeCAD doesn't allow 2 objs with same label
obj.Label = obj.Label + " to delete"
nobj.Label = label
for n in todel:
from draftutils import todo
todo.ToDo.delay(FreeCAD.ActiveDocument.removeObject, n)
def makeCurtainWall(baseobj=None, name=None):
"""
Creates a curtain wall object in the active document.
Parameters
----------
baseobj : Part::FeaturePython, optional
The base object for the curtain wall. Defaults to None.
name : str, optional
The name to assign to the created curtain wall. Defaults to None.
Returns
-------
Part::FeaturePython
The created curtain wall object.
"""
import ArchCurtainWall
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
return
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "CurtainWall")
obj.Label = name if name else translate("Arch", "Curtain Wall")
ArchCurtainWall.CurtainWall(obj)
if FreeCAD.GuiUp:
ArchCurtainWall.ViewProviderCurtainWall(obj.ViewObject)
if baseobj:
obj.Base = baseobj
if FreeCAD.GuiUp:
baseobj.ViewObject.hide()
return obj
def makeEquipment(baseobj=None, placement=None, name=None):
"""
Creates an equipment object from the given base object in the active document.
Parameters
----------
baseobj : Part::FeaturePython or Mesh::Feature, optional
The base object for the equipment. Defaults to None.
placement : Placement, optional
The placement of the equipment. Defaults to None.
name : str, optional
The name to assign to the created equipment. Defaults to None.
Returns
-------
Part::FeaturePython
The created equipment object.
"""
import ArchEquipment
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
return
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "Equipment")
obj.Label = name if name else translate("Arch", "Equipment")
ArchEquipment._Equipment(obj)
if baseobj:
if baseobj.isDerivedFrom("Mesh::Feature"):
obj.Mesh = baseobj
else:
obj.Base = baseobj
if placement:
obj.Placement = placement
if FreeCAD.GuiUp:
ArchEquipment._ViewProviderEquipment(obj.ViewObject)
if baseobj:
baseobj.ViewObject.hide()
return obj
def makeFence(section, post, path):
"""
Creates a fence object in the active document.
Parameters
----------
section : Part::FeaturePython
The section profile of the fence.
post : Part::FeaturePython
The post profile of the fence.
path : Part::FeaturePython
The path along which the fence is created.
Returns
-------
Part::FeaturePython
The created fence object.
"""
import ArchFence
obj = FreeCAD.ActiveDocument.addObject('Part::FeaturePython', 'Fence')
ArchFence._Fence(obj)
obj.Section = section
obj.Post = post
obj.Path = path
if FreeCAD.GuiUp:
ArchFence._ViewProviderFence(obj.ViewObject)
ArchFence.hide(section)
ArchFence.hide(post)
ArchFence.hide(path)
return obj
def makeFrame(baseobj, profile, name=None):
"""Creates a frame object from a base sketch (or any other object containing wires) and a
profile object (an extrudable 2D object containing faces or closed wires).
Parameters
----------
baseobj : Part::FeaturePython
The base object containing wires to define the frame.
profile : Part::FeaturePython
The profile object, an extrudable 2D object containing faces or closed wires.
name : str, optional
The name to assign to the created frame. Defaults to None.
Returns
-------
Part::FeaturePython
The created frame object.
"""
import ArchFrame
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
return
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "Frame")
obj.Label = name if name else translate("Arch", "Frame")
ArchFrame._Frame(obj)
if FreeCAD.GuiUp:
ArchFrame._ViewProviderFrame(obj.ViewObject)
if baseobj:
obj.Base = baseobj
if profile:
obj.Profile = profile
if FreeCAD.GuiUp:
profile.ViewObject.hide()
return obj
def makeGrid(name=None):
"""
Creates a grid object in the active document.
Parameters
----------
name : str, optional
The name to assign to the created grid. Defaults to None.
Returns
-------
Part::FeaturePython
The created grid object.
"""
import ArchGrid
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "Grid")
obj.Label = name if name else translate("Arch", "Grid")
ArchGrid.ArchGrid(obj)
if FreeCAD.GuiUp:
ArchGrid.ViewProviderArchGrid(obj.ViewObject)
obj.ViewObject.Transparency = 85
FreeCAD.ActiveDocument.recompute()
return obj
def makeMaterial(name=None, color=None, transparency=None):
"""
Creates a material object in the active document.
Parameters
----------
name : str, optional
The name to assign to the created material. Defaults to None.
color : tuple of float, optional
The RGB color of the material. Defaults to None.
transparency : float, optional
The transparency level of the material. Defaults to None.
Returns
-------
App::MaterialObjectPython
The created material object.
"""
import ArchMaterial
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
return
obj = FreeCAD.ActiveDocument.addObject("App::MaterialObjectPython", "Material")
obj.Label = name if name else translate("Arch", "Material")
ArchMaterial._ArchMaterial(obj)
if FreeCAD.GuiUp:
ArchMaterial._ViewProviderArchMaterial(obj.ViewObject)
getMaterialContainer().addObject(obj)
if color:
obj.Color = color[:3]
if len(color) > 3:
obj.Transparency = color[3] * 100
if transparency:
obj.Transparency = transparency
return obj
def makeMultiMaterial(name=None):
"""
Creates a multi-material object in the active document.
Parameters
----------
name : str, optional
The name to assign to the created multi-material. Defaults to None.
Returns
-------
App::FeaturePython
The created multi-material object.
"""
import ArchMaterial
obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython", "MultiMaterial")
obj.Label = name if name else translate("Arch", "MultiMaterial")
ArchMaterial._ArchMultiMaterial(obj)
if FreeCAD.GuiUp:
ArchMaterial._ViewProviderArchMultiMaterial(obj.ViewObject)
getMaterialContainer().addObject(obj)
return obj
def getMaterialContainer():
"""
Returns a group object to store materials in the active document.
Returns
-------
App::DocumentObjectGroupPython
The material container object.
"""
import ArchMaterial
for obj in FreeCAD.ActiveDocument.Objects:
if obj.Name == "MaterialContainer":
return obj
obj = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroupPython", "MaterialContainer")
obj.Label = "Materials"
ArchMaterial._ArchMaterialContainer(obj)
if FreeCAD.GuiUp:
ArchMaterial._ViewProviderArchMaterialContainer(obj.ViewObject)
return obj
def getDocumentMaterials():
"""
Retrieves all material objects in the active document.
Returns
-------
list of App::MaterialObjectPython
A list of all material objects in the document.
"""
for obj in FreeCAD.ActiveDocument.Objects:
if obj.Name == "MaterialContainer":
mats = []
for o in obj.Group:
if o.isDerivedFrom("App::MaterialObjectPython"):
mats.append(o)
return mats
return []
def makePanel(baseobj=None, length=0, width=0, thickness=0, placement=None, name=None):
"""
Creates a panel element based on the given profile object and the given
extrusion thickness. If no base object is given, you can also specify
length and width for a simple cubic object.
Parameters
----------
baseobj : Part::FeaturePython, optional
The base profile object for the panel. Defaults to None.
length : float, optional
The length of the panel. Defaults to 0.
width : float, optional
The width of the panel. Defaults to 0.
thickness : float, optional
The thickness of the panel. Defaults to 0.
placement : Placement, optional
The placement of the panel. Defaults to None.
name : str, optional
The name to assign to the created panel. Defaults to None.
Returns
-------
Part::FeaturePython
The created panel object.
"""
import ArchPanel
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
return
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "Panel")
obj.Label = name if name else translate("Arch", "Panel")
ArchPanel._Panel(obj)
if FreeCAD.GuiUp:
ArchPanel._ViewProviderPanel(obj.ViewObject)
if baseobj:
obj.Base = baseobj
if FreeCAD.GuiUp:
obj.Base.ViewObject.hide()
if width:
obj.Width = width
if thickness:
obj.Thickness = thickness
if length:
obj.Length = length
return obj
def makePanelCut(panel, name=None):
"""
Creates a 2D view of the given panel in the 3D space, positioned at the origin.
Parameters
----------
panel : Part::FeaturePython
The panel object to create a 2D view for.
name : str, optional
The name to assign to the created panel cut. Defaults to None.
Returns
-------
Part::FeaturePython
The created panel cut object.
"""
import ArchPanel
view = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "PanelCut")
view.Label = name if name else translate("Arch", "View of") + " " + panel.Label
ArchPanel.PanelCut(view)
view.Source = panel
if FreeCAD.GuiUp:
ArchPanel.ViewProviderPanelCut(view.ViewObject)
return view
def makePanelSheet(panels=[], name=None):
"""
Creates a sheet with the given panel cuts in the 3D space, positioned at the origin.
Parameters
----------
panels : list of Part::FeaturePython, optional
A list of panel cuts to include in the sheet. Defaults to an empty list.
name : str, optional
The name to assign to the created panel sheet. Defaults to None.
Returns
-------
Part::FeaturePython
The created panel sheet object.
"""
import ArchPanel
sheet = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "PanelSheet")
sheet.Label = name if name else translate("Arch", "PanelSheet")
ArchPanel.PanelSheet(sheet)
if panels:
sheet.Group = panels
if FreeCAD.GuiUp:
ArchPanel.ViewProviderPanelSheet(sheet.ViewObject)
return sheet
def makePipe(baseobj=None, diameter=0, length=0, placement=None, name=None):
"""
Creates a pipe object from the given base object or specified dimensions.
Parameters
----------
baseobj : Part::FeaturePython, optional
The base object for the pipe. Defaults to None.
diameter : float, optional
The diameter of the pipe. Defaults to 0.
length : float, optional
The length of the pipe. Defaults to 0.
placement : Placement, optional
The placement of the pipe. Defaults to None.
name : str, optional
The name to assign to the created pipe. Defaults to None.
Returns
-------
Part::FeaturePython
The created pipe object.
"""
import ArchPipe
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
return
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "Pipe")
obj.Label = name if name else translate("Arch", "Pipe")
ArchPipe._ArchPipe(obj)
if FreeCAD.GuiUp:
ArchPipe._ViewProviderPipe(obj.ViewObject)
if baseobj:
baseobj.ViewObject.hide()
if baseobj:
obj.Base = baseobj
else:
if length:
obj.Length = length
else:
obj.Length = 1000
if diameter:
obj.Diameter = diameter
else:
obj.Diameter = params.get_param_arch("PipeDiameter")
obj.Width = obj.Diameter
obj.Height = obj.Diameter
if placement:
obj.Placement = placement
return obj
def makePipeConnector(pipes, radius=0, name=None):
"""
Creates a connector between the given pipes.
Parameters
----------
pipes : list of Part::FeaturePython
A list of pipe objects to connect.
radius : float, optional
The curvature radius of the connector. Defaults to 0, which uses the diameter of the first pipe.
name : str, optional
The name to assign to the created connector. Defaults to None.
Returns
-------
Part::FeaturePython
The created pipe connector object.
"""
import ArchPipe
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
return
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "Connector")
obj.Label = name if name else translate("Arch", "Connector")
ArchPipe._ArchPipeConnector(obj)
obj.Pipes = pipes
if not radius:
radius = pipes[0].Diameter
obj.Radius = radius
if FreeCAD.GuiUp:
ArchPipe._ViewProviderPipe(obj.ViewObject)
return obj
def makeProfile(profile=[0, 'REC', 'REC100x100', 'R', 100, 100]):
"""
Creates a profile object based on the given profile data.
Parameters
----------
profile : list, optional
A list defining the profile data. Defaults to [0, 'REC', 'REC100x100', 'R', 100, 100].
Returns
-------
Part::Part2DObjectPython
The created profile object.
"""
import ArchProfile
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
return
obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython", "Profile")
obj.Label = profile[2] + "_"
if profile[3] == "C":
ArchProfile._ProfileC(obj, profile)
elif profile[3] == "H":
ArchProfile._ProfileH(obj, profile)
elif profile[3] == "R":
ArchProfile._ProfileR(obj, profile)
elif profile[3] == "RH":
ArchProfile._ProfileRH(obj, profile)
elif profile[3] == "U":
ArchProfile._ProfileU(obj, profile)
elif profile[3] == "L":
ArchProfile._ProfileL(obj, profile)
elif profile[3] == "T":
ArchProfile._ProfileT(obj, profile)
else:
print("Profile not supported")
if FreeCAD.GuiUp:
ArchProfile.ViewProviderProfile(obj.ViewObject)
return obj
def makeProject(sites=None, name=None):
"""Create an Arch project.
If sites are provided, add them as children of the new project.
Parameters
----------
sites: list of <Part::FeaturePython>, optional
Sites to add as children of the project. Ultimately this could be
anything, however.
name: str, optional
The label for the project.
Returns
-------
<Part::FeaturePython>
The created project.
Notes
-----
This function is deprecated and will be removed in a future version.
The NativeIFC project is the new way to create IFC projects.
"""
import ArchProject
import Part
if not FreeCAD.ActiveDocument:
return FreeCAD.Console.PrintError("No active document. Aborting\n")
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "Project")
obj.Label = name if name else translate("Arch", "Project")
ArchProject._Project(obj)
if FreeCAD.GuiUp:
ArchProject._ViewProviderProject(obj.ViewObject)
if sites:
obj.Group = sites
return obj
def makeRebar(baseobj=None, sketch=None, diameter=None, amount=1, offset=None, name=None):
"""
Creates a reinforcement bar object.
Parameters
----------
baseobj : Part::FeaturePython, optional
The structural object to host the rebar. Defaults to None.
sketch : Part::FeaturePython, optional
The sketch defining the rebar profile. Defaults to None.
diameter : float, optional
The diameter of the rebar. Defaults to None.
amount : int, optional
The number of rebars. Defaults to 1.
offset : float, optional
The offset distance for the rebar. Defaults to None.
name : str, optional
The name to assign to the created rebar. Defaults to None.
Returns
-------
Part::FeaturePython
The created rebar object.
"""
import ArchRebar
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
return
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "Rebar")
obj.Label = name if name else translate("Arch", "Rebar")
ArchRebar._Rebar(obj)
if FreeCAD.GuiUp:
ArchRebar._ViewProviderRebar(obj.ViewObject)
if baseobj and sketch:
if hasattr(sketch, "AttachmentSupport"):
if sketch.AttachmentSupport:
if isinstance(sketch.AttachmentSupport, tuple):
if sketch.AttachmentSupport[0] == baseobj:
sketch.AttachmentSupport = None
elif sketch.AttachmentSupport == baseobj:
sketch.AttachmentSupport = None
obj.Base = sketch
if FreeCAD.GuiUp:
sketch.ViewObject.hide()
obj.Host = baseobj
elif sketch and not baseobj:
# a rebar could be based on a wire without the existence of a Structure
obj.Base = sketch
if FreeCAD.GuiUp:
sketch.ViewObject.hide()
obj.Host = None
elif baseobj and not sketch:
obj.Shape = baseobj.Shape
if diameter:
obj.Diameter = diameter
else:
obj.Diameter = params.get_param_arch("RebarDiameter")
obj.Amount = amount
obj.Document.recompute()
if offset is not None:
obj.OffsetStart = offset
obj.OffsetEnd = offset
else:
obj.OffsetStart = params.get_param_arch("RebarOffset")
obj.OffsetEnd = params.get_param_arch("RebarOffset")
obj.Mark = obj.Label
return obj
def makeReference(filepath=None, partname=None, name=None):
"""
Creates an Arch reference object.
Parameters
----------
filepath : str, optional
The file path of the external reference. Defaults to None.
partname : str, optional
The name of the part in the external file. Defaults to None.
name : str, optional
The name to assign to the created reference. Defaults to None.
Returns
-------
Part::FeaturePython
The created reference object.
"""
import ArchReference
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
return
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "ArchReference")
obj.Label = name if name else translate("Arch", "External Reference")
ArchReference.ArchReference(obj)
if FreeCAD.GuiUp:
ArchReference.ViewProviderArchReference(obj.ViewObject)
if filepath:
obj.File = filepath
if partname:
obj.Part = partname
import Draft
Draft.select(obj)
return obj
def makeRoof(baseobj=None,
facenr=0,
angles=[45.0],
run=[250.0],
idrel=[-1],
thickness=[50.0],
overhang=[100.0],
name=None):
"""
Creates a roof object based on a closed wire or an object.
Parameters
----------
baseobj : Part::FeaturePython, optional
The base object for the roof. Defaults to None.
facenr : int, optional
The face number to use as the base. Defaults to 0.
angles : list of float, optional
The angles for each edge of the roof. Defaults to [45.0].
run : list of float, optional
The run distances for each edge. Defaults to [250.0].
idrel : list of int, optional
The relative IDs for each edge. Defaults to [-1].
thickness : list of float, optional
The thickness of the roof for each edge. Defaults to [50.0].
overhang : list of float, optional
The overhang distances for each edge. Defaults to [100.0].
name : str, optional
The name to assign to the created roof. Defaults to None.
Returns
-------
Part::FeaturePython
The created roof object.
Notes
-----
1. If the base object is a solid the roof uses its shape.
2. The angles, run, idrel, thickness, and overhang lists are automatically
completed to match the number of edges in the wire.
"""
import ArchRoof
import Part
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
return
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "Roof")
obj.Label = name if name else translate("Arch", "Roof")
baseWire = None
ArchRoof._Roof(obj)
if FreeCAD.GuiUp:
ArchRoof._ViewProviderRoof(obj.ViewObject)
if baseobj:
obj.Base = baseobj
if hasattr(obj.Base, "Shape"):
if obj.Base.Shape.Solids:
if FreeCAD.GuiUp:
obj.Base.ViewObject.hide()
else:
if (obj.Base.Shape.Faces and obj.Face):
baseWire = obj.Base.Shape.Faces[obj.Face - 1].Wires[0]
if FreeCAD.GuiUp:
obj.Base.ViewObject.hide()
elif obj.Base.Shape.Wires:
baseWire = obj.Base.Shape.Wires[0]
if FreeCAD.GuiUp:
obj.Base.ViewObject.hide()
if baseWire:
if baseWire.isClosed():
if FreeCAD.GuiUp:
obj.Base.ViewObject.hide()
edges = Part.__sortEdges__(baseWire.Edges)
ln = len(edges)
obj.Angles = ArchRoof.adjust_list_len(angles, ln, angles[0])
obj.Runs = ArchRoof.adjust_list_len(run, ln, run[0])
obj.IdRel = ArchRoof.adjust_list_len(idrel, ln, idrel[0])
obj.Thickness = ArchRoof.adjust_list_len(thickness, ln, thickness[0])
obj.Overhang = ArchRoof.adjust_list_len(overhang, ln, overhang[0])
obj.Face = facenr
return obj
def makeSchedule():
"""
Creates a schedule object in the active document.
Returns
-------
App::FeaturePython
The created schedule object.
"""
import ArchSchedule
obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython", "Schedule")
obj.Label = translate("Arch", "Schedule")
ArchSchedule._ArchSchedule(obj)
if FreeCAD.GuiUp:
ArchSchedule._ViewProviderArchSchedule(obj.ViewObject)
if hasattr(obj, "CreateSpreadsheet") and obj.CreateSpreadsheet:
obj.Proxy.getSpreadSheet(obj, force=True)
return obj
def makeSectionPlane(objectslist=None, name=None):
"""
Creates a section plane object including the given objects.
Parameters
----------
objectslist : list of Part::FeaturePython, optional
A list of objects to include in the section plane. If no object is given, the whole
document will be considered. Defaults to None.
name : str, optional
The name to assign to the created section plane. Defaults to None.
Returns
-------
App::FeaturePython
The created section plane object.
"""
import ArchSectionPlane
import Draft
import WorkingPlane
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
return
obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython", "Section")
obj.Label = name if name else translate("Arch", "Section")
ArchSectionPlane._SectionPlane(obj)
if FreeCAD.GuiUp:
ArchSectionPlane._ViewProviderSectionPlane(obj.ViewObject)
if objectslist:
obj.Objects = objectslist
bb = FreeCAD.BoundBox()
for o in Draft.get_group_contents(objectslist):
if hasattr(o, "Shape") and hasattr(o.Shape, "BoundBox"):
bb.add(o.Shape.BoundBox)
obj.Placement = WorkingPlane.get_working_plane().get_placement()
obj.Placement.Base = bb.Center
if FreeCAD.GuiUp:
margin = bb.XLength * 0.1
obj.ViewObject.DisplayLength = bb.XLength + margin
obj.ViewObject.DisplayHeight = bb.YLength + margin
return obj
def makeSite(objectslist=None, baseobj=None, name=None):
"""
Creates a site object including the given objects.
Parameters
----------
objectslist : list of Part::FeaturePython, optional
A list of objects to include in the site. Defaults to None.
baseobj : Part::FeaturePython, optional
The base object for the site. Defaults to None.
name : str, optional
The name to assign to the created site. Defaults to None.
Returns
-------
Part::FeaturePython
The created site object.
"""
import ArchSite
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
return
import Part
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "Site")
obj.Label = name if name else translate("Arch", "Site")
ArchSite._Site(obj)
if FreeCAD.GuiUp:
ArchSite._ViewProviderSite(obj.ViewObject)
if objectslist:
obj.Group = objectslist
if baseobj:
import Part
if isinstance(baseobj, Part.Shape):
obj.Shape = baseobj
else:
obj.Terrain = baseobj
return obj
def makeSpace(objects=None, baseobj=None, name=None):
"""Creates a space object from the given objects.
Parameters
----------
objects : object or List(<SelectionObject>) or App::PropertyLinkSubList, optional
The object or selection set that defines the space. If a single object is given,
it becomes the base shape for the object. If the object or selection set contains
subelements, these will be used as the boundaries to create the space. By default None.
baseobj : object or List(<SelectionObject>) or App::PropertyLinkSubList, optional
Currently unimplemented, it replaces and behaves in the same way as the objects parameter
if defined. By default None.
name : str, optional
The user-facing name to assign to the space object's label. By default None, in
which case the label is set to "Space".
Returns
-------
Part::FeaturePython
The created space object.
Notes
-----
The objects parameter can be passed using either of these different formats:
1. Single object (e.g. a Part::Feature document object). Will be used as the space's base
shape.::
objects = <Part::Feature>
2. List of selection objects, as provided by ``Gui.Selection.getSelectionEx()``. This
requires the GUI to be active. The `SubObjects` property of each selection object in the
list defines the space's boundaries. If the list contains a single selection object without
subobjects, or with only one subobject, the object in its ``Object`` property is used as
the base shape.::
objects = [<SelectionObject>, ...]
3. A list of tuples that can be assigned to an ``App::PropertyLinkSubList`` property. Each
tuple contains a document object and a nested tuple of subobjects that define the boundaries. If
the list contains a single tuple without a nested subobjects tuple, or a subobjects tuple
with only one subobject, the object in the tuple is used as the base shape.::
objects = [(obj1, ("Face1")), (obj2, ("Face1")), ...]
objects = [(obj, ("Face1", "Face2", "Face3", "Face4"))]
"""
import ArchSpace
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
return
space = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "Space")
space.Label = name if name else translate("Arch", "Space")
ArchSpace._Space(space)
if FreeCAD.GuiUp:
ArchSpace._ViewProviderSpace(space.ViewObject)
if baseobj:
objects = baseobj
if objects:
if not isinstance(objects, list):
objects = [objects]
isSingleObject = lambda objs: len(objs) == 1
# We assume that the objects list is not a mixed set. The type of the first
# object will determine the type of the set.
# Input to this function can come into three different formats. First convert it
# to a common format: [ (<Part::Feature>, ["Face1", ...]), ... ]
if (hasattr(objects[0], "isDerivedFrom") and
objects[0].isDerivedFrom("Gui::SelectionObject")):
# Selection set: convert to common format
# [<SelectionObject>, ...]
objects = [(obj.Object, obj.SubElementNames) for obj in objects]
elif (isinstance(objects[0], tuple) or isinstance(objects[0], list)):
# Tuple or list of object with subobjects: pass unmodified
# [ (<Part::Feature>, ["Face1", ...]), ... ]
pass
else:
# Single object: assume anything else passed is a single object with no
# boundaries.
# [ <Part::Feature> ]
objects = [(objects[0], [])]
if isSingleObject(objects):
# For a single object, having boundaries is determined by them being defined
# as more than one subelement (e.g. two faces)
boundaries = [obj for obj in objects if len(obj[1]) > 1]
else:
boundaries = [obj for obj in objects if obj[1]]
if isSingleObject(objects) and not boundaries:
space.Base = objects[0][0]
if FreeCAD.GuiUp:
objects[0][0].ViewObject.hide()
else:
space.Proxy.addSubobjects(space, boundaries)
return space
def addSpaceBoundaries(space, subobjects):
"""Adds the given subobjects as defining boundaries of the given space.
Parameters
----------
space : ArchSpace._Space
Arch space object to add the boundaries to.
subobjects : List(<SelectionObject>) or App::PropertyLinkSubList
List of boundaries to add to the space.
Notes
-----
The subobjects parameter can be passed using either of these different formats:
1. List of selection objects, as provided by ``Gui.Selection.getSelectionEx()``. This
requires the GUI to be active. The `SubObjects` property of each selection object in the
list defines the boundaries to add to the space.::
subobjects = [<SelectionObject>, ...]
2. A list of tuples that can be assigned to an ``App::PropertyLinkSubList`` property. Each
tuple contains a document object and a nested tuple of subobjects that define the boundaries
to add.::
subobjects = [(obj1, ("Face1")), (obj2, ("Face1")), ...]
subobjects = [(obj, ("Face1", "Face2", "Face3", "Face4"))]
"""
import Draft
if Draft.getType(space) == "Space":
space.Proxy.addSubobjects(space, subobjects)
def removeSpaceBoundaries(space, subobjects):
"""Remove the given subobjects as defining boundaries of the given space.
Parameters
----------
space : ArchSpace._Space
Arch space object to remove the boundaries from.
subobjects : List(<SelectionObject>) or App::PropertyLinkSubList
List of boundaries to remove from the space.
Notes
-----
The subobjects parameter can be passed using either of these different formats:
1. List of selection objects, as provided by ``Gui.Selection.getSelectionEx()``. This
requires the GUI to be active. The `SubObjects` property of each selection object in the
list defines the boundaries to remove from the space.::
subobjects = [<SelectionObject>, ...]
2. A list of tuples that can be assigned to an ``App::PropertyLinkSubList`` property. Each
tuple contains a document object and a nested tuple of subobjects that define the boundaries
to remove.::
subobjects = [(obj1, ("Face1")), (obj2, ("Face1")), ...]
subobjects = [(obj, ("Face1", "Face2", "Face3", "Face4"))]
"""
import Draft
if Draft.getType(space) == "Space":
space.Proxy.removeSubobjects(space, subobjects)
def makeStairs(baseobj=None, length=None, width=None, height=None, steps=None, name=None):
"""
Creates a stairs object with the given attributes.
Parameters
----------
baseobj : Part::FeaturePython, optional
The base object for the stairs. Defaults to None.
length : float, optional
The length of the stairs. Defaults to None.
width : float, optional
The width of the stairs. Defaults to None.
height : float, optional
The height of the stairs. Defaults to None.
steps : int, optional
The number of steps. Defaults to None.
name : str, optional
The name to assign to the created stairs. Defaults to None.
Returns
-------
Part::FeaturePython
The created stairs object.
"""
import ArchStairs
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
return
stairs = []
additions = []
label = name if name else translate("Arch", "Stairs")
def setProperty(obj, length, width, height, steps):
"""setProperty(obj,length,width,height,steps): sets up the basic properties for this stair"""
if length:
obj.Length = length
else:
obj.Length = params.get_param_arch("StairsLength")
if width:
obj.Width = width
else:
obj.Width = params.get_param_arch("StairsWidth")
if height:
obj.Height = height
else:
obj.Height = params.get_param_arch("StairsHeight")
if steps:
obj.NumberOfSteps = steps
obj.Structure = "Massive"
obj.StructureThickness = 150
obj.DownSlabThickness = 150
obj.UpSlabThickness = 150
obj.RailingOffsetLeft = 60
obj.RailingOffsetRight = 60
obj.RailingHeightLeft = 900
obj.RailingHeightRight = 900
if baseobj:
if not isinstance(baseobj, list):
baseobj = [baseobj]
lenSelection = len(baseobj)
if lenSelection > 1:
stair = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "Stairs")
stair.Label = label
ArchStairs._Stairs(stair)
stairs.append(stair)
i = 1
else:
i = 0
for baseobjI in baseobj:
stair = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "Stairs")
stair.Label = label
ArchStairs._Stairs(stair)
stairs.append(stair)
stairs[i].Base = baseobjI
if steps:
stepsI = steps
else:
stepsI = 20
setProperty(stairs[i], None, width, height, stepsI)
if i > 1:
additions.append(stairs[i])
stairs[i].LastSegment = stairs[i - 1]
else:
if len(stairs) > 1: # i.e. length >1, have a 'master' staircase created
stairs[0].Base = stairs[1]
i += 1
if lenSelection > 1:
stairs[0].Additions = additions
else:
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "Stairs")
obj.Label = label
ArchStairs._Stairs(obj)
setProperty(obj, length, width, height, steps)
stairs.append(obj)
if FreeCAD.GuiUp:
if baseobj:
for stair in stairs:
ArchStairs._ViewProviderStairs(stair.ViewObject)
else:
ArchStairs._ViewProviderStairs(obj.ViewObject)
if stairs:
for stair in stairs:
stair.recompute()
makeRailing(stairs)
# return stairs - all other functions expect one object as return value
return stairs[0]
else:
obj.recompute()
return obj
def makeRailing(stairs):
"""
Creates railings for the given stairs.
Parameters
----------
stairs : list of Part::FeaturePython
The stairs objects to add railings to.
Returns
-------
None
"""
import ArchPipe
def makeRailingLorR(stairs, side="L"):
"""makeRailingLorR(stairs,side="L"): Creates a railing on the given side of the stairs, L or R"""
for stair in reversed(stairs):
if side == "L":
outlineLR = stair.OutlineLeft
outlineLRAll = stair.OutlineLeftAll
stairRailingLR = "RailingLeft"
elif side == "R":
outlineLR = stair.OutlineRight
outlineLRAll = stair.OutlineRightAll
stairRailingLR = "RailingRight"
if outlineLR or outlineLRAll:
lrRail = makePipe(baseobj=None, diameter=0, length=0, placement=None, name=translate("Arch", "Railing"))
if outlineLRAll:
setattr(stair, stairRailingLR, lrRail)
break
elif outlineLR:
setattr(stair, stairRailingLR, lrRail)
if stairs is None:
sel = FreeCADGui.Selection.getSelection()
sel0 = sel[0]
stairs = []
# TODO currently consider 1st selected object, then would tackle multiple objects?
if Draft.getType(sel[0]) == "Stairs":
stairs.append(sel0)
if Draft.getType(sel0.Base) == "Stairs":
stairs.append(sel0.Base)
additions = sel0.Additions
for additionsI in additions:
if Draft.getType(additionsI) == "Stairs":
stairs.append(additionsI)
else:
stairs.append(sel[0])
else:
print("No Stairs object selected")
return
makeRailingLorR(stairs, "L")
makeRailingLorR(stairs, "R")
def makeTruss(baseobj=None, name=None):
"""
Creates a truss object from the given base object.
Parameters
----------
baseobj : Part::FeaturePython, optional
The base object for the truss. Defaults to None.
name : str, optional
The name to assign to the created truss. Defaults to None.
Returns
-------
Part::FeaturePython
The created truss object.
"""
import ArchTruss
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
return
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "Truss")
obj.Label = name if name else translate("Arch", "Truss")
ArchTruss.Truss(obj)
if FreeCAD.GuiUp:
ArchTruss.ViewProviderTruss(obj.ViewObject)
if baseobj:
obj.Base = baseobj
if FreeCAD.GuiUp:
baseobj.ViewObject.hide()
return obj
def makeWall(baseobj=None,height=None,length=None,width=None,align=None,offset=None,face=None,name=None):
"""Create a wall based on a given object, and returns the generated wall.
TODO: It is unclear what defines which units this function uses.
Parameters
----------
baseobj: <Part::Feature>, optional
The base object with which to build the wall. This can be a sketch, a
draft object, a face, or a solid. It can also be left as None.
height: float, optional
The height of the wall.
length: float, optional
The length of the wall. Not used if the wall is based off an object.
Will use Arch default if left empty.
width: float, optional
The width of the wall. Not used if the base object is a face. Will use
Arch default if left empty.
align: str, optional
Either "Center", "Left", or "Right". Effects the alignment of the wall
on its baseline.
face: int, optional
The index number of a face on the given baseobj, to base the wall on.
name: str, optional
The name to give to the created wall.
Returns
-------
<Part::FeaturePython>
Returns the generated wall.
Notes
-----
1. Creates a new <Part::FeaturePython> object, and turns it into a parametric wall
object. This <Part::FeaturePython> object does not yet have any shape.
2. The wall then uses the baseobj.Shape as the basis to extrude out a wall shape,
giving the new <Part::FeaturePython> object a shape.
3. It then hides the original baseobj.
"""
import ArchWall
import Draft
from draftutils import params
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
return
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "Wall")
if name:
obj.Label = name
else:
obj.Label = translate("Arch", "Wall")
ArchWall._Wall(obj)
if FreeCAD.GuiUp:
ArchWall._ViewProviderWall(obj.ViewObject)
if baseobj:
if hasattr(baseobj, 'Shape') or baseobj.isDerivedFrom("Mesh::Feature"):
obj.Base = baseobj
else:
FreeCAD.Console.PrintWarning(str(translate("Arch", "Walls can only be based on Part or Mesh objects")))
if face:
obj.Face = face
if length:
obj.Length = length
if width:
obj.Width = width
else:
obj.Width = params.get_param_arch("WallWidth")
if height:
obj.Height = height
else:
obj.Height = params.get_param_arch("WallHeight")
if offset:
obj.Offset = offset
else:
obj.Offset = params.get_param_arch("WallOffset")
if align:
obj.Align = align
else:
obj.Align = ["Center", "Left", "Right"][params.get_param_arch("WallAlignment")]
if obj.Base and FreeCAD.GuiUp:
if Draft.getType(obj.Base) != "Space":
obj.Base.ViewObject.hide()
return obj
def joinWalls(walls, delete=False):
"""Join the given list of walls into one sketch-based wall.
Take the first wall in the list, and adds on the other walls in the list.
Return the modified first wall.
Setting delete to True, will delete the other walls. Only join walls
if the walls have the same width, height and alignment.
Parameters
----------
walls : list of <Part::FeaturePython>
List containing the walls to add to the first wall in the list. Walls must
be based off a base object.
delete : bool, optional
If True, deletes the other walls in the list. Defaults to False.
Returns
-------
Part::FeaturePython
The joined wall object.
"""
import Part
import Draft
import ArchWall
if not walls:
return None
if not isinstance(walls, list):
walls = [walls]
if not ArchWall.areSameWallTypes(walls):
return None
deleteList = []
base = walls.pop()
if base.Base:
if base.Base.Shape.Faces:
return None
# Use ArchSketch if SketchArch add-on is present
if Draft.getType(base.Base) == "ArchSketch":
sk = base.Base
else:
try:
import ArchSketchObject
newSk = ArchSketchObject.makeArchSketch()
except:
if Draft.getType(base.Base) != "Sketcher::SketchObject":
newSk = FreeCAD.ActiveDocument.addObject("Sketcher::SketchObject", "WallTrace")
else:
newSk = None
if newSk:
sk = Draft.makeSketch(base.Base, autoconstraints=True, addTo=newSk)
base.Base = sk
else:
sk = base.Base
for w in walls:
if w.Base:
if not w.Base.Shape.Faces:
for e in w.Base.Shape.Edges:
l = e.Curve
if isinstance(l, Part.Line):
l = Part.LineSegment(e.Vertexes[0].Point, e.Vertexes[-1].Point)
sk.addGeometry(l)
deleteList.append(w.Name)
if delete:
for n in deleteList:
FreeCAD.ActiveDocument.removeObject(n)
FreeCAD.ActiveDocument.recompute()
base.ViewObject.show()
return base
def makeWindow(baseobj=None, width=None, height=None, parts=None, name=None):
"""
Creates a window object based on the given base object.
Parameters
----------
baseobj : Part::FeaturePython, optional
The base object for the window. Defaults to None.
width : float, optional
The width of the window. Defaults to None.
height : float, optional
The height of the window. Defaults to None.
parts : list, optional
The parts of the window. Defaults to None.
name : str, optional
The name to assign to the created window. Defaults to None.
Returns
-------
Part::FeaturePython
The created window object.
"""
import ArchWindow
import Draft
from draftutils import todo
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
return
if baseobj:
if Draft.getType(baseobj) == "Window":
obj = Draft.clone(baseobj)
return obj
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "Window")
ArchWindow._Window(obj)
if name:
obj.Label = name
else:
obj.Label = translate("Arch", "Window")
if FreeCAD.GuiUp:
ArchWindow._ViewProviderWindow(obj.ViewObject)
if width:
obj.Width = width
if height:
obj.Height = height
if baseobj:
obj.Normal = baseobj.Placement.Rotation.multVec(FreeCAD.Vector(0, 0, -1))
obj.Base = baseobj
if parts is not None:
obj.WindowParts = parts
else:
if baseobj:
if baseobj.getLinkedObject().isDerivedFrom("Part::Part2DObject"):
# create default component
if baseobj.Shape.Wires:
tp = "Frame"
if len(baseobj.Shape.Wires) == 1:
tp = "Solid panel"
i = 0
ws = ''
for w in baseobj.Shape.Wires:
if w.isClosed():
if ws: ws += ","
ws += "Wire" + str(i)
i += 1
obj.WindowParts = ["Default", tp, ws, "1", "0"]
else:
# bind properties from base obj if existing
for prop in ["Height", "Width", "Subvolume", "Tag", "Description", "Material"]:
for p in baseobj.PropertiesList:
if (p == prop) or p.endswith("_" + prop):
obj.setExpression(prop, baseobj.Name + "." + p)
if obj.Base and FreeCAD.GuiUp:
obj.Base.ViewObject.DisplayMode = "Wireframe"
obj.Base.ViewObject.hide()
todo.ToDo.delay(ArchWindow.recolorize, [obj.Document.Name, obj.Name])
return obj