Skip to content

Commit

Permalink
Arch: Frame object - fixes #1166, #1314
Browse files Browse the repository at this point in the history
  • Loading branch information
yorikvanhavre committed Dec 22, 2013
1 parent d83cec2 commit 90a80da
Show file tree
Hide file tree
Showing 10 changed files with 2,419 additions and 7 deletions.
1 change: 1 addition & 0 deletions src/Mod/Arch/Arch.py
Expand Up @@ -42,3 +42,4 @@
from ArchSpace import *
from ArchStairs import *
from ArchRebar import *
from ArchFrame import *
149 changes: 149 additions & 0 deletions src/Mod/Arch/ArchFrame.py
@@ -0,0 +1,149 @@
#***************************************************************************
#* *
#* Copyright (c) 2013 *
#* 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,FreeCADGui,Draft,ArchComponent,DraftVecUtils,ArchCommands
from FreeCAD import Vector
from PyQt4 import QtCore
from DraftTools import translate

__title__="FreeCAD Arch Frame"
__author__ = "Yorik van Havre"
__url__ = "http://www.freecadweb.org"


def makeFrame(base,profile,name="Frame"):
"""makeFrame(base,profile,[name]): 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)"""
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name)
_Frame(obj)
_ViewProviderFrame(obj.ViewObject)
obj.Base = base
obj.Profile = profile
#profile.ViewObject.hide()

class _CommandFrame:
"the Arch Frame command definition"

def GetResources(self):
return {'Pixmap' : 'Arch_Frame',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Arch_Frame","Frame"),
'Accel': "F, R",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_Frame","Creates a frame object from a planar 2D object and a profile")}

def Activated(self):
s = FreeCADGui.Selection.getSelection()
if len(s) == 2:
FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Frame")))
FreeCADGui.doCommand("import Arch")
FreeCADGui.doCommand("Arch.makeFrame(FreeCAD.ActiveDocument."+s[0].Name+",FreeCAD.ActiveDocument."+s[1].Name+")")
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()


class _Frame(ArchComponent.Component):
"A parametric frame object"

def __init__(self,obj):
ArchComponent.Component.__init__(self,obj)
obj.addProperty("App::PropertyLink","Profile","Arch","The profile used to build this frame")
obj.addProperty("App::PropertyBool","Align","Arch","Specifies if the profile must be aligned with the extrusion wires")
obj.addProperty("App::PropertyVector","Offset","Arch","An offset vector between the base sketch and the frame")
obj.addProperty("App::PropertyAngle","Rotation","Arch","The rotation of the profile around its extrusion axis")
self.Type = "Frame"

def execute(self,obj):
if not obj.Base:
return
if not obj.Base.Shape:
return
if not obj.Base.Shape.Wires:
return

pl = obj.Placement
if obj.Base.Shape.Solids:
obj.Shape = obj.Base.Shape.copy()
if not pl.isNull():
obj.Placement = obj.Shape.Placement.multiply(pl)
else:
if not obj.Profile:
return
if not obj.Profile.isDerivedFrom("Part::Part2DObject"):
return
if not obj.Profile.Shape:
return
if not obj.Profile.Shape.Wires:
return
if not obj.Profile.Shape.Faces:
for w in obj.Profile.Shape.Wires:
if not w.isClosed():
return
import DraftGeomUtils, Part, math
baseprofile = obj.Profile.Shape.copy()
if not baseprofile.Faces:
f = []
for w in baseprofile.Wires:
f.append(Part.Face(w))
if len(f) == 1:
baseprofile = f[0]
else:
baseprofile = Part.makeCompound(f)
shapes = []
normal = DraftGeomUtils.getNormal(obj.Base.Shape)
for wire in obj.Base.Shape.Wires:
e = wire.Edges[0]
bvec = DraftGeomUtils.vec(e)
bpoint = e.Vertexes[0].Point
profile = baseprofile.copy()
profile.translate(bpoint.sub(profile.Placement.Base))
if obj.Align:
axis = profile.Placement.Rotation.multVec(FreeCAD.Vector(0,0,1))
angle = bvec.getAngle(axis)
if round(angle,Draft.precision()) != 0:
if round(angle,Draft.precision()) != round(math.pi,Draft.precision()):
rotaxis = axis.cross(bvec)
profile.rotate(DraftVecUtils.tup(bpoint), DraftVecUtils.tup(rotaxis), math.degrees(angle))
if obj.Rotation:
profile.rotate(DraftVecUtils.tup(bpoint), DraftVecUtils.tup(FreeCAD.Vector(bvec).normalize()), obj.Rotation)
#profile = wire.makePipeShell([profile],True,False,2) TODO buggy
profile = profile.extrude(bvec)
if obj.Offset:
if not DraftVecUtils.isNull(obj.Offset):
profile.translate(obj.Offset)
shapes.append(profile)
if shapes:
obj.Shape = Part.makeCompound(shapes)
obj.Placement = pl


class _ViewProviderFrame(ArchComponent.ViewProviderComponent):
"A View Provider for the Frame object"

def __init__(self,vobj):
ArchComponent.ViewProviderComponent.__init__(self,vobj)

def getIcon(self):
import Arch_rc
return ":/icons/Arch_Frame_Tree.svg"


FreeCADGui.addCommand('Arch_Frame',_CommandFrame())
4 changes: 2 additions & 2 deletions src/Mod/Arch/ArchRebar.py
Expand Up @@ -132,7 +132,7 @@ def __init__(self,obj):
obj.addProperty("App::PropertyLength","Spacing","Arch","The spacing between the bars")
obj.addProperty("App::PropertyVector","Direction","Arch","The direction to use to spread the bars. Keep (0,0,0) for automatic direction.")
obj.addProperty("App::PropertyFloat","Rounding","Arch","The fillet to apply to the angle of the base profile. This value is multiplied by the bar diameter.")
self.Type = "Component"
self.Type = "Rebar"
obj.setEditorMode("Spacing",1)

def getBaseAndAxis(self,obj):
Expand Down Expand Up @@ -192,7 +192,7 @@ def execute(self,obj):
circle = Part.makeCircle(obj.Diameter/2,bpoint,bvec)
circle = Part.Wire(circle)
try:
bar = wire.makePipeShell([circle],1,0,2)
bar = wire.makePipeShell([circle],True,False,2)
except:
print "Arch: error sweeping rebar profile along the base sketch"
return
Expand Down

0 comments on commit 90a80da

Please sign in to comment.