232 lines
11 KiB
Python
232 lines
11 KiB
Python
#***************************************************************************
|
|
#* *
|
|
#* Copyright (c) 2011 *
|
|
#* Yorik van Havre <yorik@uncreated.net> *
|
|
#* *
|
|
#* This program is free software; you can redistribute it and/or modify *
|
|
#* it under the terms of the GNU Lesser General Public License (LGPL) *
|
|
#* as published by the Free Software Foundation; either version 2 of *
|
|
#* the License, or (at your option) any later version. *
|
|
#* for detail see the LICENCE text file. *
|
|
#* *
|
|
#* This program 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 Library General Public License for more details. *
|
|
#* *
|
|
#* You should have received a copy of the GNU Library General Public *
|
|
#* License along with this program; if not, write to the Free Software *
|
|
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
|
#* USA *
|
|
#* *
|
|
#***************************************************************************
|
|
|
|
import FreeCAD, Draft, Part, os
|
|
from FreeCAD import Vector
|
|
import csv
|
|
|
|
if FreeCAD.GuiUp:
|
|
import FreeCADGui
|
|
from PySide import QtCore, QtGui
|
|
from DraftTools import translate
|
|
from PySide.QtCore import QT_TRANSLATE_NOOP
|
|
else:
|
|
# \cond
|
|
def translate(ctxt,txt):
|
|
return txt
|
|
def QT_TRANSLATE_NOOP(ctxt,txt):
|
|
return txt
|
|
# \endcond
|
|
|
|
## @package ArchProfile
|
|
# \ingroup ARCH
|
|
# \brief Profile tools for ArchStructure
|
|
#
|
|
# This module provides tools to build base profiles
|
|
# for Arch Strucutre elements
|
|
|
|
__title__="FreeCAD Profile"
|
|
__author__ = "Yorik van Havre"
|
|
__url__ = "http://www.freecadweb.org"
|
|
|
|
# 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
|
|
profilefiles = [os.path.join(FreeCAD.getResourceDir(),"Mod","Arch","Presets","profiles.csv"),
|
|
os.path.join(os.path.dirname(__file__),"Presets","profiles.csv")]
|
|
|
|
def readPresets():
|
|
Presets=[]
|
|
for profilefile in profilefiles:
|
|
if os.path.exists(profilefile):
|
|
try:
|
|
with open(profilefile, 'rb') as csvfile:
|
|
beamreader = csv.reader(csvfile)
|
|
bid=1 #Unique index
|
|
for row in beamreader:
|
|
if 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
|
|
|
|
def makeProfile(profile=[0,'REC','REC100x100','R',100,100]):
|
|
'''makeProfile(profile): returns a shape with the face defined by the profile data'''
|
|
obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython",profile[2])
|
|
obj.Label = translate("Arch",profile[2])
|
|
if profile[3]=="C":
|
|
_ProfileC(obj, profile)
|
|
elif profile[3]=="H":
|
|
_ProfileH(obj, profile)
|
|
elif profile[3]=="R":
|
|
_ProfileR(obj, profile)
|
|
elif profile[3]=="RH":
|
|
_ProfileRH(obj, profile)
|
|
elif profile[3]=="U":
|
|
_ProfileU(obj, profile)
|
|
else :
|
|
print("Profile not supported")
|
|
if FreeCAD.GuiUp:
|
|
Draft._ViewProviderDraft(obj.ViewObject)
|
|
return obj
|
|
|
|
class _Profile(Draft._DraftObject):
|
|
'''Superclass for Profile classes'''
|
|
|
|
def __init__(self,obj, profile):
|
|
self.Profile=profile
|
|
Draft._DraftObject.__init__(self,obj,"Profile")
|
|
|
|
|
|
class _ProfileC(_Profile):
|
|
'''A parametric circular tubeprofile. Profile data: [Outside diameter, Inside diameter]'''
|
|
|
|
def __init__(self,obj, profile):
|
|
obj.addProperty("App::PropertyLength","OutDiameter","Draft",QT_TRANSLATE_NOOP("App::Property","Outside Diameter")).OutDiameter = profile[4]
|
|
obj.addProperty("App::PropertyLength","Thickness","Draft",QT_TRANSLATE_NOOP("App::Property","Wall thickness")).Thickness = profile[5]
|
|
_Profile.__init__(self,obj,profile)
|
|
|
|
def execute(self,obj):
|
|
pl = obj.Placement
|
|
c1=Part.Circle()
|
|
c1.Radius=obj.OutDiameter.Value
|
|
c2=Part.Circle()
|
|
c2.Radius=obj.OutDiameter.Value-2*obj.Thickness.Value
|
|
cs1=c1.toShape()
|
|
cs2=c2.toShape()
|
|
p=Part.makeRuledSurface(cs2,cs1)
|
|
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):
|
|
obj.addProperty("App::PropertyLength","Width","Draft",QT_TRANSLATE_NOOP("App::Property","Width of the beam")).Width = profile[4]
|
|
obj.addProperty("App::PropertyLength","Height","Draft",QT_TRANSLATE_NOOP("App::Property","Height of the beam")).Height = profile[5]
|
|
obj.addProperty("App::PropertyLength","WebThickness","Draft",QT_TRANSLATE_NOOP("App::Property","Thickness of the web")).WebThickness = profile[6]
|
|
obj.addProperty("App::PropertyLength","FlangeThickness","Draft",QT_TRANSLATE_NOOP("App::Property","Thickness of the flanges")).FlangeThickness = profile[7]
|
|
_Profile.__init__(self,obj,profile)
|
|
|
|
def execute(self,obj):
|
|
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):
|
|
obj.addProperty("App::PropertyLength","Width","Draft",QT_TRANSLATE_NOOP("App::Property","Width of the beam")).Width = profile[4]
|
|
obj.addProperty("App::PropertyLength","Height","Draft",QT_TRANSLATE_NOOP("App::Property","Height of the beam")).Height = profile[5]
|
|
_Profile.__init__(self,obj,profile)
|
|
|
|
def execute(self,obj):
|
|
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):
|
|
obj.addProperty("App::PropertyLength","Width","Draft",QT_TRANSLATE_NOOP("App::Property","Width of the beam")).Width = profile[4]
|
|
obj.addProperty("App::PropertyLength","Height","Draft",QT_TRANSLATE_NOOP("App::Property","Height of the beam")).Height = profile[5]
|
|
obj.addProperty("App::PropertyLength","Thickness","Draft",QT_TRANSLATE_NOOP("App::Property","Thickness of the sides")).Thickness = profile[6]
|
|
_Profile.__init__(self,obj,profile)
|
|
|
|
def execute(self,obj):
|
|
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()
|
|
obj.Shape = r
|
|
obj.Placement = pl
|
|
|
|
class _ProfileU(_Profile):
|
|
'''A parametric H or I beam profile. Profile data: [width, height, web thickness, flange thickness] (see http://en.wikipedia.org/wiki/I-beam forreference)'''
|
|
|
|
def __init__(self,obj, profile):
|
|
obj.addProperty("App::PropertyLength","Width","Draft",QT_TRANSLATE_NOOP("App::Property","Width of the beam")).Width = profile[4]
|
|
obj.addProperty("App::PropertyLength","Height","Draft",QT_TRANSLATE_NOOP("App::Property","Height of the beam")).Height = profile[5]
|
|
obj.addProperty("App::PropertyLength","WebThickness","Draft",QT_TRANSLATE_NOOP("App::Property","Thickness of the webs")).WebThickness = profile[6]
|
|
obj.addProperty("App::PropertyLength","FlangeThickness","Draft",QT_TRANSLATE_NOOP("App::Property","Thickness of the flange")).FlangeThickness = profile[7]
|
|
_Profile.__init__(self,obj,profile)
|
|
|
|
def execute(self,obj):
|
|
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
|
|
|
|
|