2
#***************************************************************************
3
#* Copyright (c) 2014 Yorik van Havre <yorik@uncreated.net> *
5
#* This program is free software; you can redistribute it and/or modify *
6
#* it under the terms of the GNU Lesser General Public License (LGPL) *
7
#* as published by the Free Software Foundation; either version 2 of *
8
#* the License, or (at your option) any later version. *
9
#* for detail see the LICENCE text file. *
11
#* This program is distributed in the hope that it will be useful, *
12
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
13
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14
#* GNU Library General Public License for more details. *
16
#* You should have received a copy of the GNU Library General Public *
17
#* License along with this program; if not, write to the Free Software *
18
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
21
#***************************************************************************
23
__title__ = "FreeCAD Equipment"
24
__author__ = "Yorik van Havre"
25
__url__ = "https://www.freecad.org"
32
from PySide import QtGui
33
from draftutils.translate import translate
34
from PySide.QtCore import QT_TRANSLATE_NOOP
37
def translate(ctxt,txt):
39
def QT_TRANSLATE_NOOP(ctxt,txt):
43
## @package ArchEquipment
45
# \brief The Equipment object and tools
47
# This module provides tools to build equipment objects.
48
# Equipment is used to represent furniture and all kinds of electrical
49
# or hydraulic appliances in a building
54
def createMeshView(obj,direction=FreeCAD.Vector(0,0,-1),outeronly=False,largestonly=False):
56
"""createMeshView(obj,[direction,outeronly,largestonly]): creates a flat shape that is the
57
projection of the given mesh object in the given direction (default = on the XY plane). If
58
outeronly is True, only the outer contour is taken into consideration, discarding the inner
59
holes. If largestonly is True, only the largest segment of the given mesh will be used."""
65
if not obj.isDerivedFrom("Mesh::Feature"):
69
# 1. Flattening the mesh
75
a = v.negative().getAngle(direction)
76
l = math.cos(a)*v.Length
77
p = v.add(FreeCAD.Vector(direction).multiply(l))
78
p = DraftVecUtils.rounded(p)
81
flatmesh = Mesh.Mesh(proj)
83
# 2. Removing wrong faces
85
for f in flatmesh.Facets:
86
if f.Normal.getAngle(direction) < math.pi:
88
cleanmesh = Mesh.Mesh(facets)
92
# 3. Getting the bigger mesh from the planar segments
94
c = cleanmesh.getSeparateComponents()
97
segs = cleanmesh.getPlanarSegments(1)
100
f = [cleanmesh.Facets[i] for i in s]
101
meshes.append(Mesh.Mesh(f))
107
#Mesh.show(boundarymesh)
108
cleanmesh = boundarymesh
110
# 4. Creating a Part and getting the contour
113
for f in cleanmesh.Facets:
114
p = Part.makePolygon(f.Points+[f.Points[0]])
115
#print(p,len(p.Vertexes),p.isClosed())
119
shape = shape.fuse(p)
122
except Part.OCCError:
124
shape = shape.removeSplitter()
126
# 5. Extracting the largest wire
131
for w in shape.Wires:
132
if len(w.Vertexes) > count:
133
count = len(w.Vertexes)
138
except Part.OCCError:
139
print("Unable to produce a face from the outer wire.")
147
class _Equipment(ArchComponent.Component):
149
"The Equipment object"
151
def __init__(self,obj):
153
ArchComponent.Component.__init__(self,obj)
155
self.setProperties(obj)
156
from ArchIFC import IfcTypes
157
if "Furniture" in IfcTypes:
158
# IfcFurniture is new in IFC4
159
obj.IfcType = "Furniture"
160
elif "Furnishing Element" in IfcTypes:
161
# IFC2x3 does know a IfcFurnishingElement
162
obj.IfcType = "Furnishing Element"
164
obj.IfcType = "Building Element Proxy"
165
# Add features in the SketchArch External Add-on, if present
166
self.addSketchArchFeatures(obj)
168
def addSketchArchFeatures(self,obj,linkObj=None,mode=None):
170
To add features in the SketchArch External Add-on, if present (https://github.com/paullee0/FreeCAD_SketchArch)
171
- import ArchSketchObject module, and
172
- set properties that are common to ArchObjects (including Links) and ArchSketch
173
to support the additional features
175
To install SketchArch External Add-on, see https://github.com/paullee0/FreeCAD_SketchArch#iv-install
179
import ArchSketchObject
180
ArchSketchObject.ArchSketch.setPropertiesLinkCommon(self, obj, linkObj, mode)
184
def setProperties(self,obj):
186
pl = obj.PropertiesList
187
if not "Model" in pl:
188
obj.addProperty("App::PropertyString","Model","Equipment",QT_TRANSLATE_NOOP("App::Property","The model description of this equipment"))
189
if not "ProductURL" in pl:
190
obj.addProperty("App::PropertyString","ProductURL","Equipment",QT_TRANSLATE_NOOP("App::Property","The URL of the product page of this equipment"))
191
if not "StandardCode" in pl:
192
obj.addProperty("App::PropertyString","StandardCode","Equipment",QT_TRANSLATE_NOOP("App::Property","A standard code (MasterFormat, OmniClass,...)"))
193
if not "SnapPoints" in pl:
194
obj.addProperty("App::PropertyVectorList","SnapPoints","Equipment",QT_TRANSLATE_NOOP("App::Property","Additional snap points for this equipment"))
195
if not "EquipmentPower" in pl:
196
obj.addProperty("App::PropertyFloat","EquipmentPower","Equipment",QT_TRANSLATE_NOOP("App::Property","The electric power needed by this equipment in Watts"))
197
obj.setEditorMode("VerticalArea",2)
198
obj.setEditorMode("HorizontalArea",2)
199
obj.setEditorMode("PerimeterLength",2)
200
self.Type = "Equipment"
202
def onDocumentRestored(self,obj):
204
ArchComponent.Component.onDocumentRestored(self,obj)
205
self.setProperties(obj)
207
# Add features in the SketchArch External Add-on, if present
208
self.addSketchArchFeatures(obj)
210
def onChanged(self,obj,prop):
212
self.hideSubobjects(obj,prop)
213
ArchComponent.Component.onChanged(self,obj,prop)
215
def execute(self,obj):
223
if hasattr(obj.Base,'Shape'):
224
base = obj.Base.Shape.copy()
225
base = self.processSubShapes(obj,base,pl)
226
self.applyShape(obj,base,pl,allowinvalid=False,allownosolid=True)
228
# Execute features in the SketchArch External Add-on, if present
229
self.executeSketchArchFeatures(obj)
231
def executeSketchArchFeatures(self, obj, linkObj=None, index=None, linkElement=None):
233
To execute features in the SketchArch External Add-on (https://github.com/paullee0/FreeCAD_SketchArch)
234
- import ArchSketchObject module, and
235
- execute features that are common to ArchObjects (including Links) and ArchSketch
237
To install SketchArch External Add-on, see https://github.com/paullee0/FreeCAD_SketchArch#iv-install
240
# To execute features in SketchArch External Add-on, if present
242
import ArchSketchObject
243
# Execute SketchArch Feature - Intuitive Automatic Placement for Arch Windows/Doors, Equipment etc.
244
# see https://forum.freecad.org/viewtopic.php?f=23&t=50802
245
ArchSketchObject.updateAttachmentOffset(obj, linkObj)
249
def appLinkExecute(self, obj, linkObj, index, linkElement):
251
Default Link Execute method() -
252
See https://forum.freecad.org/viewtopic.php?f=22&t=42184&start=10#p361124
253
@realthunder added support to Links to run Linked Scripted Object's methods()
256
# Add features in the SketchArch External Add-on, if present
257
self.addSketchArchFeatures(obj, linkObj)
259
# Execute features in the SketchArch External Add-on, if present
260
self.executeSketchArchFeatures(obj, linkObj)
262
def computeAreas(self,obj):
266
class _ViewProviderEquipment(ArchComponent.ViewProviderComponent):
268
"A View Provider for the Equipment object"
270
def __init__(self,vobj):
272
ArchComponent.ViewProviderComponent.__init__(self,vobj)
277
if hasattr(self,"Object"):
278
if hasattr(self.Object,"CloneOf"):
279
if self.Object.CloneOf:
280
return ":/icons/Arch_Equipment_Clone.svg"
281
return ":/icons/Arch_Equipment_Tree.svg"
283
def attach(self, vobj):
285
self.Object = vobj.Object
286
from pivy import coin
287
sep = coin.SoSeparator()
288
self.coords = coin.SoCoordinate3()
289
sep.addChild(self.coords)
290
self.coords.point.deleteValues(0)
291
symbol = coin.SoMarkerSet()
292
symbol.markerIndex = FreeCADGui.getMarkerIndex("", 5)
296
ArchComponent.ViewProviderComponent.attach(self,vobj)
298
def updateData(self, obj, prop):
300
if prop == "SnapPoints":
302
self.coords.point.setNum(len(obj.SnapPoints))
303
self.coords.point.setValues([[p.x,p.y,p.z] for p in obj.SnapPoints])
305
self.coords.point.deleteValues(0)