FreeCAD

Форк
0
/
ArchEquipment.py 
305 строк · 11.0 Кб
1
# -*- coding: utf8 -*-
2
#***************************************************************************
3
#*   Copyright (c) 2014 Yorik van Havre <yorik@uncreated.net>              *
4
#*                                                                         *
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.                                 *
10
#*                                                                         *
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.                  *
15
#*                                                                         *
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  *
19
#*   USA                                                                   *
20
#*                                                                         *
21
#***************************************************************************
22

23
__title__  = "FreeCAD Equipment"
24
__author__ = "Yorik van Havre"
25
__url__    = "https://www.freecad.org"
26

27
import FreeCAD
28
import ArchComponent
29
import DraftVecUtils
30
if FreeCAD.GuiUp:
31
    import FreeCADGui
32
    from PySide import QtGui
33
    from draftutils.translate import translate
34
    from PySide.QtCore import QT_TRANSLATE_NOOP
35
else:
36
    # \cond
37
    def translate(ctxt,txt):
38
        return txt
39
    def QT_TRANSLATE_NOOP(ctxt,txt):
40
        return txt
41
    # \endcond
42

43
## @package ArchEquipment
44
#  \ingroup ARCH
45
#  \brief The Equipment object and tools
46
#
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
50

51

52

53

54
def createMeshView(obj,direction=FreeCAD.Vector(0,0,-1),outeronly=False,largestonly=False):
55

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."""
60

61
    import math
62
    import DraftGeomUtils
63
    import Mesh
64
    import Part
65
    if not obj.isDerivedFrom("Mesh::Feature"):
66
        return
67
    mesh = obj.Mesh
68

69
    # 1. Flattening the mesh
70
    proj = []
71
    for f in mesh.Facets:
72
        nf = []
73
        for v in f.Points:
74
            v = FreeCAD.Vector(v)
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)
79
            nf.append(p)
80
        proj.append(nf)
81
    flatmesh = Mesh.Mesh(proj)
82

83
    # 2. Removing wrong faces
84
    facets = []
85
    for f in flatmesh.Facets:
86
        if f.Normal.getAngle(direction) < math.pi:
87
            facets.append(f)
88
    cleanmesh = Mesh.Mesh(facets)
89

90
    #Mesh.show(cleanmesh)
91

92
    # 3. Getting the bigger mesh from the planar segments
93
    if largestonly:
94
        c = cleanmesh.getSeparateComponents()
95
        #print(c)
96
        cleanmesh = c[0]
97
        segs = cleanmesh.getPlanarSegments(1)
98
        meshes = []
99
        for s in segs:
100
            f = [cleanmesh.Facets[i] for i in s]
101
            meshes.append(Mesh.Mesh(f))
102
        a = 0
103
        for m in meshes:
104
            if m.Area > a:
105
                boundarymesh = m
106
                a = m.Area
107
        #Mesh.show(boundarymesh)
108
        cleanmesh = boundarymesh
109

110
    # 4. Creating a Part and getting the contour
111

112
    shape = None
113
    for f in cleanmesh.Facets:
114
        p = Part.makePolygon(f.Points+[f.Points[0]])
115
        #print(p,len(p.Vertexes),p.isClosed())
116
        try:
117
            p = Part.Face(p)
118
            if shape:
119
                shape = shape.fuse(p)
120
            else:
121
                shape = p
122
        except Part.OCCError:
123
            pass
124
    shape = shape.removeSplitter()
125

126
    # 5. Extracting the largest wire
127

128
    if outeronly:
129
        count = 0
130
        largest = None
131
        for w in shape.Wires:
132
            if len(w.Vertexes) > count:
133
                count = len(w.Vertexes)
134
                largest = w
135
        if largest:
136
            try:
137
                f = Part.Face(w)
138
            except Part.OCCError:
139
                print("Unable to produce a face from the outer wire.")
140
            else:
141
                shape = f
142

143
    return shape
144

145

146

147
class _Equipment(ArchComponent.Component):
148

149
    "The Equipment object"
150

151
    def __init__(self,obj):
152

153
        ArchComponent.Component.__init__(self,obj)
154
        obj.Proxy = self
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"
163
        else:
164
            obj.IfcType = "Building Element Proxy"
165
        # Add features in the SketchArch External Add-on, if present
166
        self.addSketchArchFeatures(obj)
167

168
    def addSketchArchFeatures(self,obj,linkObj=None,mode=None):
169
        '''
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
174

175
           To install SketchArch External Add-on, see https://github.com/paullee0/FreeCAD_SketchArch#iv-install
176
        '''
177

178
        try:
179
            import ArchSketchObject
180
            ArchSketchObject.ArchSketch.setPropertiesLinkCommon(self, obj, linkObj, mode)
181
        except:
182
            pass
183

184
    def setProperties(self,obj):
185

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"
201

202
    def onDocumentRestored(self,obj):
203

204
        ArchComponent.Component.onDocumentRestored(self,obj)
205
        self.setProperties(obj)
206

207
        # Add features in the SketchArch External Add-on, if present
208
        self.addSketchArchFeatures(obj)
209

210
    def onChanged(self,obj,prop):
211

212
        self.hideSubobjects(obj,prop)
213
        ArchComponent.Component.onChanged(self,obj,prop)
214

215
    def execute(self,obj):
216

217
        if self.clone(obj):
218
            return
219

220
        pl = obj.Placement
221
        if obj.Base:
222
            base = None
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)
227

228
        # Execute features in the SketchArch External Add-on, if present
229
        self.executeSketchArchFeatures(obj)
230

231
    def executeSketchArchFeatures(self, obj, linkObj=None, index=None, linkElement=None):
232
        '''
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
236

237
           To install SketchArch External Add-on, see https://github.com/paullee0/FreeCAD_SketchArch#iv-install
238
        '''
239

240
        # To execute features in SketchArch External Add-on, if present
241
        try:
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)
246
        except:
247
            pass
248

249
    def appLinkExecute(self, obj, linkObj, index, linkElement):
250
        '''
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()
254
        '''
255

256
        # Add features in the SketchArch External Add-on, if present
257
        self.addSketchArchFeatures(obj, linkObj)
258

259
        # Execute features in the SketchArch External Add-on, if present
260
        self.executeSketchArchFeatures(obj, linkObj)
261

262
    def computeAreas(self,obj):
263
        return
264

265

266
class _ViewProviderEquipment(ArchComponent.ViewProviderComponent):
267

268
    "A View Provider for the Equipment object"
269

270
    def __init__(self,vobj):
271

272
        ArchComponent.ViewProviderComponent.__init__(self,vobj)
273

274
    def getIcon(self):
275

276
        import Arch_rc
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"
282

283
    def attach(self, vobj):
284

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)
293
        sep.addChild(symbol)
294
        rn = vobj.RootNode
295
        rn.addChild(sep)
296
        ArchComponent.ViewProviderComponent.attach(self,vobj)
297

298
    def updateData(self, obj, prop):
299

300
        if prop == "SnapPoints":
301
            if obj.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])
304
            else:
305
                self.coords.point.deleteValues(0)
306

307

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.