From 9a3fdec662a6dfc996266dfad453a3895552f568 Mon Sep 17 00:00:00 2001 From: "Zheng, Lei" Date: Thu, 26 Jul 2018 10:58:25 +0800 Subject: [PATCH] constraint: add support for edge/face symmetric constraint --- constraint.py | 64 +++++++++++++++++++++++++++++++++++++++++++-------- solver.py | 5 +++- system.py | 5 +++- 3 files changed, 63 insertions(+), 11 deletions(-) diff --git a/constraint.py b/constraint.py index 1bae928..c3f1c12 100644 --- a/constraint.py +++ b/constraint.py @@ -10,7 +10,8 @@ _iconPath = os.path.join(utils.iconPath,'constraints') PointInfo = namedtuple('PointInfo', ('entity','params','vector')) LineInfo = namedtuple('LineInfo', ('entity','p0','p1')) -NormalInfo = namedtuple('NormalInfo', ('entity','rot','params','p0','ln')) +NormalInfo = namedtuple('NormalInfo', + ('entity','rot','params','p0','ln','p1','px','vx','pla')) PlaneInfo = namedtuple('PlaneInfo', ('entity','origin','normal')) CircleInfo = namedtuple('CurcleInfo',('entity','radius','p0')) ArcInfo = namedtuple('CurcleInfo',('entity','p1','p0','params')) @@ -128,19 +129,26 @@ def _n(solver,partInfo,subname,shape,retAll=False): nz = system.addTransform(e,*partInfo.Params,group=partInfo.Group) p0 = _p(solver,partInfo,subname,shape,True) - v = rot.inverted().multVec(p0.vector) - v.z += 1 - v = rot.multVec(v) + v0 = rot.inverted().multVec(p0.vector) + + vz = rot.multVec(FreeCAD.Vector(v0.x,v0.y,v0.z+1)) system.NameTag = nameTag + 'p1' - e = system.addPoint3dV(*v) + e = system.addPoint3dV(*vz) system.NameTag += 't' p1 = system.addTransform(e,*partInfo.Params,group=partInfo.Group) system.NameTag = nameTag + 'l' ln = system.addLineSegment(p0.entity,p1,group=partInfo.Group) - h = NormalInfo(entity=nz,rot=rot, - params=partInfo.Params, p0=p0.entity, ln=ln) + vx = rot.multVec(FreeCAD.Vector(v0.x+1,v0.y,v0.z)) + system.NameTag = nameTag + 'px' + e = system.addPoint3dV(*vx) + system.NameTag += 't' + px = system.addTransform(e,*partInfo.Params,group=partInfo.Group) + + h = NormalInfo(entity=nz, rot=rot, params=partInfo.Params, + p0=p0.entity, ln=ln, p1=p1, px=px, vx=vx, + pla=partInfo.Placement) system.log('{}: {},{}'.format(system.NameTag,h,partInfo.Group)) partInfo.EntityMap[key] = h @@ -559,6 +567,7 @@ _makeProp('OffsetX','App::PropertyDistance',getter=propGetValue) _makeProp('OffsetY','App::PropertyDistance',getter=propGetValue) _makeProp('Cascade','App::PropertyBool',internal=True) _makeProp('Multiply','App::PropertyBool',internal=True) +_makeProp('LockRotationZ','App::PropertyBool',internal=True,default=True) _makeProp('Angle','App::PropertyAngle',getter=propGetValue) _AngleProps = [ @@ -1184,6 +1193,41 @@ class PointLineDistance(Base): 'and a linear edge in 2D or 3D' +class Symmetric(Base): + _id = 48 + _entityDef = (_ln,_ln,_w) + _props = ['LockRotationZ'] + _iconName = 'Assembly_ConstraintSymmetric.svg' + _tooltip='Add a "{}" constraint to make geometry elements of two parts\n'\ + 'symmetric about a plane. The supported elements are linear edge\n'\ + 'and planar face' + + @classmethod + def prepare(cls,obj,solver): + func = cls.constraintFunc(obj,solver) + func2 = cls.constraintFunc(obj,solver,'addPointsCoincident') + if not func or not func2: + return + params = cls.getEntities(obj,solver,retAll=True) + e0,e1,w = params[:3] + ret = [] + ret.append(func(e0.p0,e1.p0,w.entity,group=solver.group)) + ret.append(func2(e0.p1,e1.p1,w.entity,group=solver.group)) + if obj.LockRotationZ: + rot = w.normal.pla.Rotation.multiply(w.normal.rot) + x1 = e0.pla.multVec(e0.vx) + x2 = e1.pla.multVec(e1.vx) + v1,v2 = utils.project2D(rot, x1, x2) + if abs(v1.x-v2.x) < abs(v1.y-v2.y): + func = cls.constraintFunc(obj,solver,'addPointsHorizontal') + else: + func = cls.constraintFunc(obj,solver,'addPointsVertical') + if func: + ret.append(func(e0.px, e1.px, w.entity, group=solver.group)) + solver.system.log('{}: {}'.format(cstrName(obj),ret)) + return ret + + class More(Base): _id = 47 _iconName = 'Assembly_ConstraintMore.svg' @@ -1229,11 +1273,13 @@ class EqualAngle(Base2): _tooltip='Add a "{}" to equate the angles between two lines or normals.' -class Symmetric(Base2): +class PointsSymmetric(Base2): _id = 16 _entityDef = (_p,_p,_w) - _iconName = 'Assembly_ConstraintSymmetric.svg' + _workplane = True + _iconName = 'Assembly_ConstraintPointsSymmetric.svg' _tooltip='Add a "{}" constraint to make two points symmetric about a plane.' + _cstrFuncName = 'addSymmetric' class SymmetricHorizontal(Base2): diff --git a/solver.py b/solver.py index 38268a8..f4ee62d 100644 --- a/solver.py +++ b/solver.py @@ -235,13 +235,16 @@ class Solver(object): p1 = self.system.addPoint3d(self.v0,self.v0,self.v1,group=g) self.system.NameTag = info.PartName + '.l' ln = self.system.addLineSegment(p0,p1,group=g) + self.system.NameTag = info.PartName + '.npx' + px = self.system.addPoint3d(self.v1,self.v0,self.v0,group=g) self.system.NameTag = info.PartName + '.w' w = self.system.addWorkplane(p,n,group=g) h = PlaneInfo(entity=w, origin=PointInfo(entity=p, params=None, vector=FreeCAD.Vector()), normal=NormalInfo(entity=n,rot=FreeCAD.Rotation(), - params=params,p0=p0,ln=ln)) + params=params,p0=p0,ln=ln,p1=p1,px=px, + vx=FreeCAD.Vector(1), pla=info.Placement)) partInfo = PartInfo(Part = info.Part, PartName = info.PartName, diff --git a/system.py b/system.py index 790f2e7..80da9d8 100644 --- a/system.py +++ b/system.py @@ -204,7 +204,10 @@ class SystemExtension(object): # We project the initial points to the first element plane, and # check for differences in x and y components of the points to # determine whether to use horizontal or vertical constraint. - v1,v2 = project2D(pln1.normal.rot, pln1.origin.vector, v) + rot = pln1.normal.pla.Rotation.multiply(pln1.normal.rot) + v1 = pln1.normal.pla.multVec(pln1.origin.vector) + v2 = pln2.normal.pla.multVec(v) + v1,v2 = project2D(rot, v1, v2) if abs(v1.x-v2.x) < abs(v1.y-v2.y): h.append(self.addPointsHorizontal( pln1.origin.entity, e, pln1.entity, group=group))