* BIM: fix issue with T-slot profile * BIM: fix issue with T-slot profile * BIM: fix issue with T-slot profile * Update ArchProfile.py: remove temp print
545 lines
24 KiB
Python
545 lines
24 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 Profile"
|
|
__author__ = "Yorik van Havre"
|
|
__url__ = "https://www.freecad.org"
|
|
|
|
## @package ArchProfile
|
|
# \ingroup ARCH
|
|
# \brief Profile tools for ArchStructure
|
|
#
|
|
# This module provides tools to build base profiles
|
|
# for Arch Structure elements
|
|
|
|
import csv
|
|
import os
|
|
|
|
import FreeCAD
|
|
import Draft
|
|
|
|
from FreeCAD import Vector
|
|
from draftutils import params
|
|
|
|
if FreeCAD.GuiUp:
|
|
from PySide import QtCore, QtGui
|
|
from PySide.QtCore import QT_TRANSLATE_NOOP
|
|
import FreeCADGui
|
|
from draftutils.translate import translate
|
|
else:
|
|
# \cond
|
|
def translate(ctxt,txt):
|
|
return txt
|
|
def QT_TRANSLATE_NOOP(ctxt,txt):
|
|
return txt
|
|
# \endcond
|
|
|
|
|
|
# Presets in the form: Class, Name, Profile type, [profile data]
|
|
# Search for profiles.csv in data/Mod/Arch/Presets and in the same folder as this file
|
|
# and in the user path
|
|
profilefiles = [os.path.join(FreeCAD.getResourceDir(),"Mod","BIM","Presets","profiles.csv"),
|
|
os.path.join(os.path.dirname(__file__),"Presets","profiles.csv"),
|
|
os.path.join(FreeCAD.getUserAppDataDir(),"BIM","profiles.csv")]
|
|
|
|
|
|
def readPresets():
|
|
|
|
Presets=[]
|
|
bid = 1 #Unique index
|
|
for profilefile in profilefiles:
|
|
if os.path.exists(profilefile):
|
|
try:
|
|
with open(profilefile, "r") as csvfile:
|
|
beamreader = csv.reader(csvfile)
|
|
for row in beamreader:
|
|
if (not row) or row[0].startswith("#"):
|
|
continue
|
|
try:
|
|
r=[bid, row[0], row[1], row[2]]
|
|
for i in range(3,len(row)):
|
|
r=r+[float(row[i])]
|
|
if not r in Presets:
|
|
Presets.append(r)
|
|
bid=bid+1
|
|
except ValueError:
|
|
print("Skipping bad line: "+str(row))
|
|
except IOError:
|
|
print("Could not open ",profilefile)
|
|
return Presets
|
|
|
|
|
|
|
|
class _Profile(Draft._DraftObject):
|
|
|
|
'''Superclass for Profile classes'''
|
|
|
|
def __init__(self,obj, profile):
|
|
self.Profile = profile
|
|
Draft._DraftObject.__init__(self,obj,"Profile")
|
|
|
|
def dumps(self):
|
|
if hasattr(self,"Profile"):
|
|
return self.Profile
|
|
|
|
def loads(self,state):
|
|
if isinstance(state,list):
|
|
self.Profile = state
|
|
self.Type = "Profile"
|
|
|
|
def cleanProperties(self, obj):
|
|
|
|
'''Remove all Profile properties'''
|
|
|
|
for prop in obj.PropertiesList:
|
|
if obj.getGroupOfProperty(prop) == "Draft":
|
|
obj.setPropertyStatus(prop, "-LockDynamic")
|
|
obj.removeProperty(prop)
|
|
|
|
|
|
class _ProfileC(_Profile):
|
|
|
|
'''A parametric circular tubeprofile. Profile data: [Outside diameter, Wall thickness]'''
|
|
|
|
def __init__(self,obj, profile):
|
|
self.cleanProperties(obj)
|
|
obj.addProperty("App::PropertyLength","OutDiameter","Draft",QT_TRANSLATE_NOOP("App::Property","Outside Diameter"), locked=True).OutDiameter = profile[4]
|
|
obj.addProperty("App::PropertyLength","Thickness","Draft",QT_TRANSLATE_NOOP("App::Property","Wall thickness"), locked=True).Thickness = profile[5]
|
|
_Profile.__init__(self,obj,profile)
|
|
|
|
def execute(self,obj):
|
|
import Part
|
|
pl = obj.Placement
|
|
c1=Part.Circle()
|
|
c1.Radius=obj.OutDiameter.Value/2
|
|
c2=Part.Circle()
|
|
c2.Radius=obj.OutDiameter.Value/2-obj.Thickness.Value
|
|
cs1=c1.toShape()
|
|
cs2=c2.toShape()
|
|
p=Part.makeRuledSurface(cs2,cs1)
|
|
p.reverse()
|
|
obj.Shape = p
|
|
obj.Placement = pl
|
|
|
|
|
|
class _ProfileH(_Profile):
|
|
|
|
'''A parametric H or I beam profile. Profile data: [width, height, web thickness, flange thickness] (see http://en.wikipedia.org/wiki/I-beam for reference)'''
|
|
|
|
def __init__(self,obj, profile):
|
|
self.cleanProperties(obj)
|
|
obj.addProperty("App::PropertyLength","Width","Draft",QT_TRANSLATE_NOOP("App::Property","Width of the beam"), locked=True).Width = profile[4]
|
|
obj.addProperty("App::PropertyLength","Height","Draft",QT_TRANSLATE_NOOP("App::Property","Height of the beam"), locked=True).Height = profile[5]
|
|
obj.addProperty("App::PropertyLength","WebThickness","Draft",QT_TRANSLATE_NOOP("App::Property","Thickness of the web"), locked=True).WebThickness = profile[6]
|
|
obj.addProperty("App::PropertyLength","FlangeThickness","Draft",QT_TRANSLATE_NOOP("App::Property","Thickness of the flanges"), locked=True).FlangeThickness = profile[7]
|
|
_Profile.__init__(self,obj,profile)
|
|
|
|
def execute(self,obj):
|
|
import Part
|
|
pl = obj.Placement
|
|
p1 = Vector(-obj.Width.Value/2,-obj.Height.Value/2,0)
|
|
p2 = Vector(obj.Width.Value/2,-obj.Height.Value/2,0)
|
|
p3 = Vector(obj.Width.Value/2,(-obj.Height.Value/2)+obj.FlangeThickness.Value,0)
|
|
p4 = Vector(obj.WebThickness.Value/2,(-obj.Height.Value/2)+obj.FlangeThickness.Value,0)
|
|
p5 = Vector(obj.WebThickness.Value/2,obj.Height.Value/2-obj.FlangeThickness.Value,0)
|
|
p6 = Vector(obj.Width.Value/2,obj.Height.Value/2-obj.FlangeThickness.Value,0)
|
|
p7 = Vector(obj.Width.Value/2,obj.Height.Value/2,0)
|
|
p8 = Vector(-obj.Width.Value/2,obj.Height.Value/2,0)
|
|
p9 = Vector(-obj.Width.Value/2,obj.Height.Value/2-obj.FlangeThickness.Value,0)
|
|
p10 = Vector(-obj.WebThickness.Value/2,obj.Height.Value/2-obj.FlangeThickness.Value,0)
|
|
p11 = Vector(-obj.WebThickness.Value/2,(-obj.Height.Value/2)+obj.FlangeThickness.Value,0)
|
|
p12 = Vector(-obj.Width.Value/2,(-obj.Height.Value/2)+obj.FlangeThickness.Value,0)
|
|
p = Part.makePolygon([p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p1])
|
|
p = Part.Face(p)
|
|
#p.reverse()
|
|
obj.Shape = p
|
|
obj.Placement = pl
|
|
|
|
|
|
class _ProfileR(_Profile):
|
|
|
|
'''A parametric rectangular beam profile based on [Width, Height]'''
|
|
|
|
def __init__(self,obj, profile):
|
|
self.cleanProperties(obj)
|
|
obj.addProperty("App::PropertyLength","Width","Draft",QT_TRANSLATE_NOOP("App::Property","Width of the beam"), locked=True).Width = profile[4]
|
|
obj.addProperty("App::PropertyLength","Height","Draft",QT_TRANSLATE_NOOP("App::Property","Height of the beam"), locked=True).Height = profile[5]
|
|
_Profile.__init__(self,obj,profile)
|
|
|
|
def execute(self,obj):
|
|
import Part
|
|
pl = obj.Placement
|
|
p1 = Vector(-obj.Width.Value/2,-obj.Height.Value/2,0)
|
|
p2 = Vector(obj.Width.Value/2,-obj.Height.Value/2,0)
|
|
p3 = Vector(obj.Width.Value/2,obj.Height.Value/2,0)
|
|
p4 = Vector(-obj.Width.Value/2,obj.Height.Value/2,0)
|
|
p = Part.makePolygon([p1,p2,p3,p4,p1])
|
|
p = Part.Face(p)
|
|
#p.reverse()
|
|
obj.Shape = p
|
|
obj.Placement = pl
|
|
|
|
|
|
class _ProfileRH(_Profile):
|
|
|
|
'''A parametric Rectangular hollow beam profile. Profile data: [width, height, thickness]'''
|
|
|
|
def __init__(self,obj, profile):
|
|
self.cleanProperties(obj)
|
|
obj.addProperty("App::PropertyLength","Width","Draft",QT_TRANSLATE_NOOP("App::Property","Width of the beam"), locked=True).Width = profile[4]
|
|
obj.addProperty("App::PropertyLength","Height","Draft",QT_TRANSLATE_NOOP("App::Property","Height of the beam"), locked=True).Height = profile[5]
|
|
obj.addProperty("App::PropertyLength","Thickness","Draft",QT_TRANSLATE_NOOP("App::Property","Thickness of the sides"), locked=True).Thickness = profile[6]
|
|
_Profile.__init__(self,obj,profile)
|
|
|
|
def execute(self,obj):
|
|
import Part
|
|
pl = obj.Placement
|
|
p1 = Vector(-obj.Width.Value/2,-obj.Height.Value/2,0)
|
|
p2 = Vector(obj.Width.Value/2,-obj.Height.Value/2,0)
|
|
p3 = Vector(obj.Width.Value/2,obj.Height.Value/2,0)
|
|
p4 = Vector(-obj.Width.Value/2,obj.Height.Value/2,0)
|
|
q1 = Vector(-obj.Width.Value/2+obj.Thickness.Value,-obj.Height.Value/2+obj.Thickness.Value,0)
|
|
q2 = Vector(obj.Width.Value/2-obj.Thickness.Value,-obj.Height.Value/2+obj.Thickness.Value,0)
|
|
q3 = Vector(obj.Width.Value/2-obj.Thickness.Value,obj.Height.Value/2-obj.Thickness.Value,0)
|
|
q4 = Vector(-obj.Width.Value/2+obj.Thickness.Value,obj.Height.Value/2-obj.Thickness.Value,0)
|
|
p = Part.makePolygon([p1,p2,p3,p4,p1])
|
|
q = Part.makePolygon([q1,q2,q3,q4,q1])
|
|
#r = Part.Face([p,q])
|
|
#r.reverse()
|
|
p = Part.Face(p)
|
|
q = Part.Face(q)
|
|
r = p.cut(q)
|
|
obj.Shape = r
|
|
obj.Placement = pl
|
|
|
|
|
|
class _ProfileU(_Profile):
|
|
|
|
'''A parametric U profile. Profile data: [width, height, web thickness, flange thickness] (see https://en.wikipedia.org/wiki/Structural_channel for reference)'''
|
|
|
|
def __init__(self,obj, profile):
|
|
self.cleanProperties(obj)
|
|
obj.addProperty("App::PropertyLength","Width","Draft",QT_TRANSLATE_NOOP("App::Property","Width of the beam"), locked=True).Width = profile[4]
|
|
obj.addProperty("App::PropertyLength","Height","Draft",QT_TRANSLATE_NOOP("App::Property","Height of the beam"), locked=True).Height = profile[5]
|
|
obj.addProperty("App::PropertyLength","WebThickness","Draft",QT_TRANSLATE_NOOP("App::Property","Thickness of the webs"), locked=True).WebThickness = profile[6]
|
|
obj.addProperty("App::PropertyLength","FlangeThickness","Draft",QT_TRANSLATE_NOOP("App::Property","Thickness of the flange"), locked=True).FlangeThickness = profile[7]
|
|
_Profile.__init__(self,obj,profile)
|
|
|
|
def execute(self,obj):
|
|
import Part
|
|
pl = obj.Placement
|
|
p1 = Vector(-obj.Width.Value/2,-obj.Height.Value/2,0)
|
|
p2 = Vector(obj.Width.Value/2,-obj.Height.Value/2,0)
|
|
p3 = Vector(obj.Width.Value/2,obj.Height.Value/2,0)
|
|
p4 = Vector(obj.Width.Value/2-obj.FlangeThickness.Value,obj.Height.Value/2,0)
|
|
p5 = Vector(obj.Width.Value/2-obj.FlangeThickness.Value,obj.WebThickness.Value-obj.Height.Value/2,0)
|
|
p6 = Vector(-obj.Width.Value/2+obj.FlangeThickness.Value,obj.WebThickness.Value-obj.Height.Value/2,0)
|
|
p7 = Vector(-obj.Width.Value/2+obj.FlangeThickness.Value,obj.Height.Value/2,0)
|
|
p8 = Vector(-obj.Width.Value/2,obj.Height.Value/2,0)
|
|
p = Part.makePolygon([p1,p2,p3,p4,p5,p6,p7,p8,p1])
|
|
p = Part.Face(p)
|
|
#p.reverse()
|
|
obj.Shape = p
|
|
obj.Placement = pl
|
|
|
|
|
|
class _ProfileL(_Profile):
|
|
|
|
'''A parametric L profile. Profile data: [width, height, thickness]'''
|
|
|
|
def __init__(self, obj, profile):
|
|
self.cleanProperties(obj)
|
|
obj.addProperty("App::PropertyLength","Width","Draft",QT_TRANSLATE_NOOP("App::Property","Width of the beam"), locked=True).Width = profile[4]
|
|
obj.addProperty("App::PropertyLength","Height","Draft",QT_TRANSLATE_NOOP("App::Property","Height of the beam"), locked=True).Height = profile[5]
|
|
obj.addProperty("App::PropertyLength","Thickness","Draft",QT_TRANSLATE_NOOP("App::Property","Thickness of the legs"), locked=True).Thickness = profile[6]
|
|
_Profile.__init__(self,obj,profile)
|
|
|
|
def execute(self,obj):
|
|
import Part
|
|
pl = obj.Placement
|
|
p1 = Vector(-obj.Width.Value/2, obj.Height.Value/2, 0)
|
|
p2 = Vector(-obj.Width.Value/2, -obj.Height.Value/2, 0)
|
|
p3 = Vector(obj.Width.Value/2, -obj.Height.Value/2, 0)
|
|
p4 = Vector(obj.Width.Value/2, -obj.Height.Value/2+obj.Thickness.Value, 0)
|
|
p5 = Vector(-obj.Width.Value/2+obj.Thickness.Value, -obj.Height.Value/2+obj.Thickness.Value, 0)
|
|
p6 = Vector(-obj.Width.Value/2+obj.Thickness.Value, obj.Height.Value/2, 0)
|
|
p = Part.makePolygon([p1,p2,p3,p4,p5,p6,p1])
|
|
p = Part.Face(p)
|
|
#p.reverse()
|
|
obj.Shape = p
|
|
obj.Placement = pl
|
|
|
|
|
|
class _ProfileT(_Profile):
|
|
|
|
'''A parametric T profile. Profile data: [width, height, web thickness, flange thickness]'''
|
|
|
|
def __init__(self, obj, profile):
|
|
self.cleanProperties(obj)
|
|
obj.addProperty("App::PropertyLength","Width","Draft",QT_TRANSLATE_NOOP("App::Property","Width of the beam"), locked=True).Width = profile[4]
|
|
obj.addProperty("App::PropertyLength","Height","Draft",QT_TRANSLATE_NOOP("App::Property","Height of the beam"), locked=True).Height = profile[5]
|
|
obj.addProperty("App::PropertyLength","WebThickness","Draft",QT_TRANSLATE_NOOP("App::Property","Thickness of the web"), locked=True).WebThickness = profile[6]
|
|
obj.addProperty("App::PropertyLength","FlangeThickness","Draft",QT_TRANSLATE_NOOP("App::Property","Thickness of the flanges"), locked=True).FlangeThickness = profile[7]
|
|
_Profile.__init__(self,obj,profile)
|
|
|
|
def execute(self,obj):
|
|
import Part
|
|
pl = obj.Placement
|
|
p1 = Vector(obj.WebThickness.Value/2, -obj.Height.Value/2, 0)
|
|
p2 = Vector(obj.WebThickness.Value/2, obj.Height.Value/2-obj.FlangeThickness.Value, 0)
|
|
p3 = Vector(obj.Width.Value/2, obj.Height.Value/2-obj.FlangeThickness.Value, 0)
|
|
p4 = Vector(obj.Width.Value/2, obj.Height.Value/2, 0)
|
|
p5 = Vector(-obj.Width.Value/2, obj.Height.Value/2, 0)
|
|
p6 = Vector(-obj.Width.Value/2, obj.Height.Value/2-obj.FlangeThickness.Value, 0)
|
|
p7 = Vector(-obj.WebThickness.Value/2, obj.Height.Value/2-obj.FlangeThickness.Value, 0)
|
|
p8 = Vector(-obj.WebThickness.Value/2, -obj.Height.Value/2, 0)
|
|
p = Part.makePolygon([p1,p2,p3,p4,p5,p6,p7,p8,p1])
|
|
p = Part.Face(p)
|
|
#p.reverse()
|
|
obj.Shape = p
|
|
obj.Placement = pl
|
|
|
|
|
|
class _ProfileTSLOT(_Profile):
|
|
|
|
'''T slot profile common made of aluminum'''
|
|
|
|
def __init__(self, obj, profile):
|
|
self.cleanProperties(obj)
|
|
obj.addProperty("App::PropertyLength","Size","Draft",QT_TRANSLATE_NOOP("App::Property","Overall size"), locked=True).Size = profile[4]
|
|
obj.addProperty("App::PropertyLength","SlotSize","Draft",QT_TRANSLATE_NOOP("App::Property","Slot size"), locked=True).SlotSize = profile[5]
|
|
obj.addProperty("App::PropertyLength","WallThickness","Draft",QT_TRANSLATE_NOOP("App::Property","Thickness of the wall"), locked=True).WallThickness = profile[6]
|
|
obj.addProperty("App::PropertyLength","TnutSlotWidth","Draft",QT_TRANSLATE_NOOP("App::Property","T-nut slot width"), locked=True).TnutSlotWidth = profile[7]
|
|
obj.addProperty("App::PropertyLength","TnutSlotDepth","Draft",QT_TRANSLATE_NOOP("App::Property","T-nut slot depth"), locked=True).TnutSlotDepth = profile[8]
|
|
obj.addProperty("App::PropertyLength","CoreSize","Draft",QT_TRANSLATE_NOOP("App::Property","Internal core size"), locked=True).CoreSize = profile[9]
|
|
obj.addProperty("App::PropertyLength","HoleDiameter","Draft",QT_TRANSLATE_NOOP("App::Property","Internal hole diameter"), locked=True).HoleDiameter = profile[10]
|
|
obj.addProperty("App::PropertyLength","FilletRadius","Draft",QT_TRANSLATE_NOOP("App::Property","Corner fillet radius"), locked=True).FilletRadius = profile[11]
|
|
_Profile.__init__(self,obj,profile)
|
|
|
|
def execute(self,obj):
|
|
import Part
|
|
import math
|
|
# import DraftGeomUtils
|
|
pl = obj.Placement
|
|
nut_depth = obj.CoreSize/2-(obj.WallThickness/math.sqrt(2))
|
|
core_dim = obj.CoreSize/2
|
|
wall_dim = obj.WallThickness
|
|
slot_dim = obj.SlotSize/2
|
|
nut_width_dim = obj.TnutSlotWidth/2
|
|
templist = list()
|
|
templist.append(Vector(nut_depth, core_dim, 0.0))
|
|
templist.append(Vector(nut_width_dim, nut_width_dim+(wall_dim/math.sqrt(2)), 0.0))
|
|
templist.append(Vector(nut_width_dim, obj.Size/2-wall_dim, 0.0))
|
|
templist.append(Vector(slot_dim, obj.Size/2-wall_dim, 0.0))
|
|
templist.append(Vector(slot_dim, obj.Size/2, 0.0))
|
|
templist.append(Vector(obj.Size/2, obj.Size/2, 0.0))
|
|
#TODO:
|
|
# add fillet four profile corners
|
|
# sub_poly1 = Part.makePolygon(templist)
|
|
# rd1=Vector(obj.Size/2-(obj.FilletRadius),obj.Size,0)
|
|
# rd2=Vector(obj.Size/2-(obj.FilletRadius-obj.FilletRadius*math.sin(math.pi/4)),obj.Size/2-(obj.FilletRadius-obj.FilletRadius*math.sin(math.pi/4)),0)
|
|
# rd3=Vector(obj.Size,obj.Size/2-(obj.FilletRadius),0)
|
|
# templist.append(Part.Arc(rd1,rd2,rd3))
|
|
templist.append(Vector(obj.Size/2, slot_dim, 0.0))
|
|
templist.append(Vector(obj.Size/2-wall_dim, slot_dim, 0.0))
|
|
templist.append(Vector(obj.Size/2-wall_dim, nut_width_dim, 0.0))
|
|
templist.append(Vector(nut_width_dim+(wall_dim/math.sqrt(2)), nut_width_dim, 0.0))
|
|
templist.append(Vector(core_dim, nut_depth, 0.0))
|
|
# sub_poly2 = Part.makePolygon(templist3)
|
|
# l1=Part.LineSegment(Vector(obj.SlotSize/2, obj.Size/2, 0.0),Vector(obj.Size/2, obj.Size/2, 0.0))
|
|
# l2=Part.LineSegment(Vector(obj.Size/2, obj.Size/2, 0.0),Vector(obj.Size/2, 2.7500000000022977, 0.0))
|
|
# round=DraftGeomUtils.fillet([l2.toShape(),l1.toShape()],obj.FilletRadius)
|
|
# wire=Part.Wire(round)
|
|
# p = Part.Shape([sub_poly1,round,sub_poly2])
|
|
# p=Part.Face(Shape.Edges)
|
|
templist2 = list()
|
|
for vec in reversed(templist):
|
|
templist2.append(Vector(vec.x,vec.y*-1,vec.z))
|
|
templist = templist + templist2
|
|
templist2.clear()
|
|
for vec in reversed(templist):
|
|
templist2.append(Vector(vec.x*-1,vec.y,vec.z))
|
|
templist = templist + templist2
|
|
templist.append(templist[0])
|
|
poly = Part.makePolygon(templist)
|
|
pf = Part.Face(poly)
|
|
hole = Part.makeCircle(obj.HoleDiameter/2, FreeCAD.Vector(0, 0, 0))
|
|
cf=Part.Face(Part.Wire(hole))
|
|
p=pf.cut(cf)
|
|
#p.reverse()
|
|
obj.Shape = p
|
|
obj.Placement = pl
|
|
|
|
|
|
class ViewProviderProfile(Draft._ViewProviderDraft):
|
|
|
|
'''General view provider for Profile classes'''
|
|
|
|
def __init__(self,vobj):
|
|
|
|
Draft._ViewProviderDraft.__init__(self,vobj)
|
|
|
|
def getIcon(self):
|
|
|
|
import Arch_rc
|
|
return ":/icons/Arch_Profile.svg"
|
|
|
|
def setEdit(self, vobj, mode):
|
|
if mode == 1 or mode == 2:
|
|
return None
|
|
|
|
taskd = ProfileTaskPanel(vobj.Object)
|
|
FreeCADGui.Control.showDialog(taskd)
|
|
return True
|
|
|
|
def unsetEdit(self, vobj, mode):
|
|
if mode == 1 or mode == 2:
|
|
return None
|
|
|
|
FreeCADGui.Control.closeDialog()
|
|
return True
|
|
|
|
|
|
class ProfileTaskPanel:
|
|
|
|
'''The editmode TaskPanel for Profile objects'''
|
|
|
|
def __init__(self,obj):
|
|
|
|
self.obj = obj
|
|
self.Profile = None
|
|
if hasattr(obj.Proxy,"Profile"):
|
|
self.Profile = obj.Proxy.Profile
|
|
if isinstance(self.obj.Proxy,_ProfileC):
|
|
self.type = "C"
|
|
elif isinstance(self.obj.Proxy,_ProfileH):
|
|
self.type = "H"
|
|
elif isinstance(self.obj.Proxy,_ProfileR):
|
|
self.type = "R"
|
|
elif isinstance(self.obj.Proxy,_ProfileRH):
|
|
self.type = "RH"
|
|
elif isinstance(self.obj.Proxy,_ProfileU):
|
|
self.type = "U"
|
|
elif isinstance(self.obj.Proxy,_ProfileL):
|
|
self.type = "L"
|
|
elif isinstance(self.obj.Proxy,_ProfileT):
|
|
self.type = "T"
|
|
elif isinstance(self.obj.Proxy,_ProfileTSLOT):
|
|
self.type = "TSLOT"
|
|
else:
|
|
self.type = "Building Element Proxy"
|
|
self.form = QtGui.QWidget()
|
|
layout = QtGui.QVBoxLayout(self.form)
|
|
self.comboCategory = QtGui.QComboBox(self.form)
|
|
layout.addWidget(self.comboCategory)
|
|
self.comboProfile = QtGui.QComboBox(self.form)
|
|
layout.addWidget(self.comboProfile)
|
|
QtCore.QObject.connect(self.comboCategory, QtCore.SIGNAL("currentTextChanged(QString)"), self.changeCategory)
|
|
QtCore.QObject.connect(self.comboProfile, QtCore.SIGNAL("currentIndexChanged(int)"), self.changeProfile)
|
|
# Read preset profiles and add relevant ones
|
|
self.categories = []
|
|
self.presets = readPresets()
|
|
for pre in self.presets:
|
|
if pre[1] not in self.categories:
|
|
self.categories.append(pre[1])
|
|
self.comboCategory.addItem(" ")
|
|
if self.categories:
|
|
self.comboCategory.addItems(self.categories)
|
|
# Find current profile by label
|
|
if not self.Profile:
|
|
for pre in self.presets:
|
|
if self.type == pre[1]:
|
|
if self.obj.Label in pre[2]:
|
|
self.Profile = pre
|
|
break
|
|
if not self.Profile:
|
|
# try to find by size
|
|
if hasattr(self.obj,"Width") and hasattr(self.obj,"Height"):
|
|
for pre in self.presets:
|
|
if self.type == pre[1]:
|
|
if abs(self.obj.Width - self.Profile[4]) < 0.1 and \
|
|
abs(self.obj.Height - self.Profile[5]) < 0.1:
|
|
self.Profile = pre
|
|
break
|
|
if self.Profile:
|
|
origprofile = list(self.Profile) # the operation below will change self.profile
|
|
self.comboCategory.setCurrentIndex(1+self.categories.index(origprofile[1]))
|
|
self.changeCategory(origprofile[1])
|
|
self.comboProfile.setCurrentIndex(self.currentpresets.index(origprofile))
|
|
self.retranslateUi(self.form)
|
|
|
|
def changeCategory(self,text):
|
|
|
|
self.comboProfile.clear()
|
|
self.currentpresets = []
|
|
for pre in self.presets:
|
|
if pre[1] == text:
|
|
self.currentpresets.append(pre)
|
|
f = FreeCAD.Units.Quantity(pre[4],FreeCAD.Units.Length).getUserPreferred()
|
|
d = params.get_param("Decimals",path="Units")
|
|
s1 = str(round(pre[4]/f[1],d))
|
|
s2 = str(round(pre[5]/f[1],d))
|
|
s3 = str(f[2])
|
|
self.comboProfile.addItem(pre[2]+" ("+s1+"x"+s2+s3+")")
|
|
|
|
def changeProfile(self,idx):
|
|
|
|
self.Profile = self.currentpresets[idx]
|
|
|
|
def accept(self):
|
|
|
|
self.obj.Label = self.Profile[2] + "_"
|
|
if self.Profile:
|
|
if self.Profile[3]=="C":
|
|
_ProfileC(self.obj, self.Profile)
|
|
elif self.Profile[3]=="H":
|
|
_ProfileH(self.obj, self.Profile)
|
|
elif self.Profile[3]=="R":
|
|
_ProfileR(self.obj, self.Profile)
|
|
elif self.Profile[3]=="RH":
|
|
_ProfileRH(self.obj, self.Profile)
|
|
elif self.Profile[3]=="U":
|
|
_ProfileU(self.obj, self.Profile)
|
|
elif self.Profile[3]=="L":
|
|
_ProfileL(self.obj, self.Profile)
|
|
elif self.Profile[3]=="T":
|
|
_ProfileT(self.obj, self.Profile)
|
|
elif self.Profile[3]=="TSLOT":
|
|
_ProfileTSLOT(self.obj, self.Profile)
|
|
else:
|
|
print("Profile not supported")
|
|
|
|
FreeCAD.ActiveDocument.recompute()
|
|
FreeCADGui.ActiveDocument.resetEdit()
|
|
return True
|
|
|
|
def reject(self):
|
|
|
|
FreeCADGui.ActiveDocument.resetEdit()
|
|
return True
|
|
|
|
def retranslateUi(self, TaskPanel):
|
|
|
|
self.form.setWindowTitle(self.type+" "+QtGui.QApplication.translate("Arch", "Profile", None))
|