assembly: add support for Origin

This commit is contained in:
Zheng, Lei 2018-06-03 00:26:07 +08:00
parent 200ad8795f
commit 4b1a3b9de6
6 changed files with 337 additions and 36 deletions

View File

@ -0,0 +1,236 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="svg2816"
height="64px"
width="64px"
inkscape:version="0.91 r13725"
sodipodi:docname="Assembly_Add_Origin.svg">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1375"
inkscape:window-height="876"
id="namedview8"
showgrid="true"
inkscape:snap-global="true"
inkscape:zoom="6.1487323"
inkscape:cx="34.380017"
inkscape:cy="21.217521"
inkscape:window-x="65"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:current-layer="svg2816"
inkscape:snap-bbox="true">
<inkscape:grid
type="xygrid"
id="grid2985"
empspacing="2"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<defs
id="defs2818">
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4023"
id="linearGradient4029"
x1="45"
y1="34"
x2="50"
y2="59"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
id="linearGradient4023">
<stop
style="stop-color:#8ae234;stop-opacity:1;"
offset="0"
id="stop4025" />
<stop
style="stop-color:#4e9a06;stop-opacity:1"
offset="1"
id="stop4027" />
</linearGradient>
</defs>
<metadata
id="metadata2821">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<dc:title>Path-Heights</dc:title>
<dc:date>2016-05-15</dc:date>
<dc:relation>http://www.freecadweb.org/wiki/index.php?title=Artwork</dc:relation>
<dc:publisher>
<cc:Agent>
<dc:title>FreeCAD</dc:title>
</cc:Agent>
</dc:publisher>
<dc:identifier>FreeCAD/src/Mod/Path/Gui/Resources/icons/Path-Heights.svg</dc:identifier>
<dc:rights>
<cc:Agent>
<dc:title>FreeCAD LGPL2+</dc:title>
</cc:Agent>
</dc:rights>
<cc:license>https://www.gnu.org/copyleft/lesser.html</cc:license>
<dc:contributor>
<cc:Agent>
<dc:title>[agryson] Alexander Gryson</dc:title>
</cc:Agent>
</dc:contributor>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="g4279"
transform="translate(0.60592319,-3.1240777)">
<g
transform="matrix(0.98185387,-0.18963905,0.18963905,0.98185387,-8.2586686,1.7494738)"
id="g4269">
<path
style="fill:none;stroke:#172a04;stroke-width:8;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
d="M 8.5539856,45.653481 36.927779,35.989795"
id="path6397-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<g
id="g4191"
transform="matrix(0.92948156,0.36886858,-0.36886858,0.92948156,-5.161415,3.5397752)">
<path
sodipodi:nodetypes="sssss"
inkscape:connector-curvature="0"
id="path6514"
d="m 56.301546,9.8662949 c 2.380189,2.4586491 2.356371,7.1457861 0.562268,8.4303771 -1.794104,1.284591 -3.882477,1.614145 -6.262666,-0.844506 -2.380188,-2.45865 -3.71292,-5.928709 -2.506121,-7.9449766 1.206798,-2.0162674 5.82633,-2.0995447 8.206519,0.3591055 z"
style="fill:#8ae234;fill-opacity:1;stroke:#172a04;stroke-width:2.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:32.20000076;stroke-opacity:1" />
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path6475-3-5"
d="M 57.675023,17.196253 C 59.125757,14.079173 55.786493,7.1175596 49.88913,8.2225984 L 61.683856,6.0125218 Z"
style="fill:#73d216;stroke:#172a04;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:32.20000076;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path6571"
d="m 54.164074,9.3183964 6.831678,-1.301668"
style="fill:none;stroke:#8ae234;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path6475-3-5-1"
d="M 57.656587,17.221263 C 59.10732,14.104182 55.768056,7.1425689 49.870693,8.2476077 L 61.665419,6.0375311 Z"
style="fill:none;stroke:#172a04;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:32.20000076;stroke-opacity:1" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path6397-3-7"
d="M 28.282635,34.084733 51.090922,14.636314"
style="fill:none;stroke:#73d216;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path6397-3-7-7"
d="M 27.716662,33.28548 50.524948,13.83706"
style="fill:none;stroke:#8ae234;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
</g>
</g>
<g
transform="matrix(0.92948156,0.36886858,-0.36886858,0.92948156,-5.161415,3.5397752)"
id="g4184">
<path
style="fill:none;stroke:#0b1521;stroke-width:8;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
d="m 20.574,14.664038 7.708635,19.420695"
id="path6419"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#3465a4;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
d="m 20.574,14.664038 7.708635,19.420695"
id="path6419-6"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#729fcf;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
d="m 19.591106,14.848211 7.708636,19.420696"
id="path6419-6-2"
inkscape:connector-curvature="0" />
<path
style="fill:#3465a4;stroke:#0b1521;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:32.20000076;stroke-opacity:1"
d="M 25.784624,9.8940192 C 24.447439,13.983293 16.814109,16.316975 13.522059,15.037005 l 1.87136,-11.7316318 z"
id="path6475"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="fill:none;stroke:#729fcf;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:32.20000076;stroke-opacity:1"
d="m 23.173929,10.50514 c -1.088305,1.548234 -4.835095,3.046266 -7.403563,2.95258 l 1.047955,-6.930515 z"
id="path6475-6"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
</g>
<g
transform="matrix(0.98847886,-0.15135896,0.15135896,0.98847886,-24.876777,16.01178)"
id="g4177">
<path
style="fill:none;stroke:#280000;stroke-width:8;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
d="M 28.282635,34.084733 48.721677,45.429535"
id="path6397"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#cc0000;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
d="M 28.282635,34.084733 48.721677,45.429535"
id="path6397-5"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#ef2929;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
d="M 27.563165,34.802163 48.002207,46.146965"
id="path6397-5-0"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:#cc0000;stroke:#280000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:32.20000076;stroke-opacity:1"
d="m 44.154236,49.799985 c -1.00857,-4.115837 4.453037,-9.683235 8.029404,-10.133289 l 4.620086,10.887343 z"
id="path6475-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="fill:none;stroke:#ef2929;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:32.20000076;stroke-opacity:1"
d="m 46.097609,48.060608 c 0.127899,-1.831027 2.617666,-4.866574 4.923727,-5.991774 l 2.785967,6.402357 z"
id="path6475-6-2"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
</g>
</g>
<g
transform="translate(1.3346056,1.1625214)"
id="g4265">
<path
sodipodi:nodetypes="ccccccccccccc"
inkscape:connector-curvature="0"
id="path4019"
d="m 33,43 0,8 10,0 0,10 8,0 0,-10 10,0 0,-8 -10,0 0,-10 -8,0 0,10 z"
style="fill:url(#linearGradient4029);fill-opacity:1;stroke:#172a04;stroke-width:1.99999988;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path4021"
d="m 45,35 0,10 -10,0 0,4 10,0 0,10 4,0 0,-10 10,0 0,-4 -10,0 0,-10 z"
style="fill:none;stroke:#8ae234;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.8 KiB

View File

@ -590,7 +590,7 @@ class ViewProviderAsmElementSketch(ViewProviderAsmElement):
ElementInfo = namedtuple('AsmElementInfo', ('Parent','SubnameRef','Part',
'PartName','Placement','Object','Subname','Shape'))
def getElementInfo(parent, subname):
def getElementInfo(parent, subname, checkPlacement=False):
'''Return a named tuple containing the part object element information
Parameters:
@ -723,12 +723,14 @@ def getElementInfo(parent, subname):
# object. We trim the subname reference to be relative to the part
# object. And obtain the shape before part's Placement by setting
# 'transform' to False
if checkPlacement and not hasattr(part,'Placement'):
raise RuntimeError('part has no placement')
subname = '.'.join(names[1:])
shape = utils.getElementShape((part,subname))
if not shape:
raise RuntimeError('cannot get geometry element from {}.{}'.format(
part.Name,subname))
pla = part.Placement
pla = getattr(part,'Placement',FreeCAD.Placement())
obj = part.getLinkedObject(False)
partName = part.Name
@ -1743,6 +1745,13 @@ class ViewProviderAssembly(ViewProviderAsmGroup):
self._movingPart = None
super(ViewProviderAssembly,self).__init__(vobj)
def onDelete(self,vobj,_subs):
for o in vobj.Object.Proxy.getPartGroup().Group:
if o.TypeId == 'App::Origin':
o.Document.removeObject(o.Name)
break
return True
def _convertSubname(self,owner,subname):
sub = subname.split('.')
if not sub:
@ -1833,6 +1842,8 @@ class AsmWorkPlane(object):
def __init__(self,obj):
obj.addProperty("App::PropertyLength","Length","Base")
obj.addProperty("App::PropertyLength","Width","Base")
obj.addProperty("App::PropertyBool","Fixed","Base")
obj.Fixed = True
obj.Length = 10
obj.Width = 10
obj.Proxy = self
@ -1926,38 +1937,66 @@ class AsmWorkPlane(object):
BoundBox = bbox)
@staticmethod
def make(sels=None,name='Workplane', tp=0, undo=True):
def make(sels=None,name=None, tp=0, undo=True):
info = AsmWorkPlane.getSelection(sels)
doc = info.PartGroup.Document
if undo:
FreeCAD.setActiveTransaction('Assembly create workplane')
try:
obj = doc.addObject('Part::FeaturePython',name)
AsmWorkPlane(obj)
ViewProviderAsmWorkPlane(obj.ViewObject)
if tp==1:
pla = FreeCAD.Placement(info.Placement.Base,
FreeCAD.Rotation(FreeCAD.Vector(0,1,0),-90))
elif tp==2:
pla = FreeCAD.Placement(info.Placement.Base,
FreeCAD.Rotation(FreeCAD.Vector(1,0,0),90))
logger.debug('make {}'.format(tp))
if tp == 3:
obj = None
for o in info.PartGroup.Group:
if o.TypeId == 'App::Origin':
obj = o
break
if not obj:
if not name:
name = 'Origin'
obj = doc.addObject('App::Origin',name)
info.PartGroup.setLink({-1:obj})
info.PartGroup.recompute(True)
shape = Part.getShape(info.PartGroup)
if not shape.isNull():
bbox = shape.BoundBox
if bbox.isValid():
obj.ViewObject.Size = tuple([
max(abs(a),abs(b)) for a,b in (
(bbox.XMin,bbox.XMax),
(bbox.YMin,bbox.YMax),
(bbox.ZMin,bbox.ZMax)) ])
else:
pla = info.Placement
if utils.isVertex(info.Shape):
obj.Length = obj.Width = 0
elif utils.isLinearEdge(info.Shape):
if info.BoundBox.isValid():
obj.Length = info.BoundBox.DiagonalLength
obj.Width = 0
pla = FreeCAD.Placement(pla.Base,pla.Rotation.multiply(
FreeCAD.Rotation(FreeCAD.Vector(0,1,0),90)))
elif info.BoundBox.isValid():
obj.Length = obj.Width = info.BoundBox.DiagonalLength
if not name:
name = 'Workplane'
obj = doc.addObject('Part::FeaturePython',name)
AsmWorkPlane(obj)
ViewProviderAsmWorkPlane(obj.ViewObject)
if tp==1:
pla = FreeCAD.Placement(info.Placement.Base,
FreeCAD.Rotation(FreeCAD.Vector(0,1,0),-90))
elif tp==2:
pla = FreeCAD.Placement(info.Placement.Base,
FreeCAD.Rotation(FreeCAD.Vector(1,0,0),90))
else:
pla = info.Placement
obj.Placement = pla
if utils.isVertex(info.Shape):
obj.Length = obj.Width = 0
elif utils.isLinearEdge(info.Shape):
if info.BoundBox.isValid():
obj.Length = info.BoundBox.DiagonalLength
obj.Width = 0
pla = FreeCAD.Placement(pla.Base,pla.Rotation.multiply(
FreeCAD.Rotation(FreeCAD.Vector(0,1,0),90)))
elif info.BoundBox.isValid():
obj.Length = obj.Width = info.BoundBox.DiagonalLength
obj.Placement = pla
obj.recompute(True)
info.PartGroup.setLink({-1:obj})
obj.recompute(True)
info.PartGroup.setLink({-1:obj})
if undo:
FreeCAD.closeActiveTransaction()
@ -1965,6 +2004,7 @@ class AsmWorkPlane(object):
FreeCADGui.Selection.addSelection(info.SelObj,
info.SelSubname + info.PartGroup.Name + '.' + obj.Name + '.')
FreeCADGui.runCommand('Std_TreeSelection')
FreeCADGui.Selection.setVisible(True)
return obj
except Exception:
if undo:

View File

@ -469,10 +469,18 @@ class Constraint(ProxyType):
return mcs.getProxy(obj).prepare(obj,solver)
@classmethod
def getFixedParts(mcs,solver,cstrs):
def getFixedParts(mcs,solver,cstrs,parts):
firstInfo = None
found = False
ret = set()
from .assembly import isTypeOf, AsmWorkPlane
for obj in parts:
if not hasattr(obj,'Placement'):
ret.add(obj)
elif isTypeOf(obj,AsmWorkPlane) and getattr(obj,'Fixed',False):
ret.add(obj)
found = len(ret)
for obj in cstrs:
cstr = mcs.getProxy(obj)
if cstr.hasFixedPart(obj):

22
gui.py
View File

@ -390,6 +390,8 @@ class AsmCmdAddWorkplane(AsmCmdBase):
_menuText = 'Add workplane'
_iconName = 'Assembly_Add_Workplane.svg'
_toolbarName = None
_accel = 'A, P'
_makeType = 0
@classmethod
def checkActive(cls):
@ -405,34 +407,48 @@ class AsmCmdAddWorkplane(AsmCmdBase):
cls._active = False
@classmethod
def Activated(cls,idx):
def Activated(cls,idx=0):
_ = idx
from . import assembly
assembly.AsmWorkPlane.make(tp=idx)
assembly.AsmWorkPlane.make(tp=cls._makeType)
class AsmCmdAddWorkplaneXZ(AsmCmdAddWorkplane):
_id = 10
_menuText = 'Add XZ workplane'
_iconName = 'Assembly_Add_WorkplaneXZ.svg'
_makeType = 1
class AsmCmdAddWorkplaneZY(AsmCmdAddWorkplane):
_id = 11
_menuText = 'Add ZY workplane'
_iconName = 'Assembly_Add_WorkplaneZY.svg'
_makeType = 2
class AsmCmdAddOrigin(AsmCmdAddWorkplane):
_id = 14
_menuText = 'Add Origin'
_iconName = 'Assembly_Add_Origin.svg'
_makeType = 3
_accel = 'A, O'
class AsmCmdAddWorkplaneGroup(AsmCmdAddWorkplane):
_id = 12
_toolbarName = AsmCmdBase._toolbarName
_cmds = (AsmCmdAddWorkplane.getName(),
AsmCmdAddWorkplaneXZ.getName(),
AsmCmdAddWorkplaneZY.getName())
AsmCmdAddWorkplaneZY.getName(),
AsmCmdAddOrigin.getName())
@classmethod
def GetCommands(cls):
return cls._cmds
@classmethod
def Activated(cls,idx=0):
FreeCADGui.runCommand(cls._cmds[idx])
class AsmCmdUp(AsmCmdBase):
_id = 6

View File

@ -244,9 +244,8 @@ def getMovingElementInfo():
objName(selObj),selSub))
if len(sels[0].SubElementNames)==1:
info = getElementInfo(ret[0].Assembly,ret[0].Subname)
if not info:
return
info = getElementInfo(ret[0].Assembly,
ret[0].Subname, checkPlacement=True)
return MovingPartInfo(SelObj=selObj,
SelSubname=selSub,
Hierarchy=ret,
@ -270,10 +269,11 @@ def getMovingElementInfo():
assembly = ret[-1].Assembly
for r in ret2:
if assembly == r.Assembly:
info = getElementInfo(r.Assembly,r.Subname,checkPlacement=True)
return MovingPartInfo(SelObj=selObj,
SelSubname=selSub,
Hierarchy=ret2,
ElementInfo=getElementInfo(r.Assembly,r.Subname))
ElementInfo=info)
raise RuntimeError('not child parent selection')
def canMovePart():

View File

@ -56,7 +56,8 @@ class Solver(object):
roty = FreeCAD.Rotation(FreeCAD.Vector(1,0,0),90)
self.ny = self.system.addNormal3dV(*utils.getNormal(roty))
self._fixedParts = Constraint.getFixedParts(self,cstrs)
parts = assembly.Proxy.getPartGroup().Group
self._fixedParts = Constraint.getFixedParts(self,cstrs,parts)
for part in self._fixedParts:
self._fixedElements.add((part,None))