예제 #1
0
    def derivedExecute(self,obj):
        self.assureGenerator(obj)
        self.updateReadonlyness(obj)
        
        # Apply links
        if obj.AxisLink:
            if lattice2BaseFeature.isObjectLattice(obj.AxisLink):
                lattice2Executer.warning(obj,"For polar array, axis link is expected to be a regular shape. Lattice objct was supplied instead, it's going to be treated as a generic shape.")
                
            #resolve the link        
            if len(obj.AxisLinkSubelement) > 0:
                linkedShape = obj.AxisLink.Shape.getElement(obj.AxisLinkSubelement)
            else:
                linkedShape = obj.AxisLink.Shape

            #Type check
            if linkedShape.ShapeType != 'Edge':
                raise ValueError('Axis link must be an edge; it is '+linkedShape.ShapeType+' instead.')
            
            #prepare
            dir = App.Vector()
            point = App.Vector()
            if isinstance(linkedShape.Curve, Part.Line):
                dir = linkedShape.Curve.EndPoint - linkedShape.Curve.StartPoint
                point = linkedShape.Curve.StartPoint
            elif isinstance(linkedShape.Curve, Part.Circle):
                dir = linkedShape.Curve.Axis
                point = linkedShape.Curve.Center
            else:
                raise ValueError("Edge " + repr(linkedShape) + " can't be used to derive an axis. It must be either a line or a circle/arc.")
            
            #apply
            if obj.AxisDirIsDriven:
                obj.AxisDir = dir
            if obj.AxisPointIsDriven:
                obj.AxisPoint = point
        
        self.generator.execute()
        
        # cache properties into variables
        radius = float(obj.Radius)
        values = [float(strv) for strv in obj.Values]
        
        # compute initial vector. It is to be perpendicular to Axis
        rot_ini = lattice2GeomUtils.makeOrientationFromLocalAxes(ZAx= obj.AxisDir)
        overallPlacement = App.Placement(obj.AxisPoint, rot_ini)
        
        # Make the array
        output = [] # list of placements
        for ang in values:
            p = Part.Vertex()
            localrot = App.Rotation(App.Vector(0,0,1), ang)
            localtransl = localrot.multVec(App.Vector(radius,0,0))
            localplm = App.Placement(localtransl, localrot)
            resultplm = overallPlacement.multiply(localplm)
            if obj.OrientMode == 'None':
                resultplm.Rotation = App.Rotation()
            output.append(resultplm)

        return output
예제 #2
0
def mirrorPlacement(placement, pivotPlacement, flipX, flipY, flipZ):
    """mirrorPlacement(placement, pivotPlacement, flipX, flipY, flipZ): mirrors a placement. Y axis of placement is adjusted to keep the placement's CS right-handed."""
    plmM = pivotPlacement.toMatrix()
    mirrM = App.Base.Matrix()
    if flipX: mirrM.A11 = -1
    if flipY: mirrM.A22 = -1
    if flipZ: mirrM.A33 = -1
    m = plmM.multiply(mirrM.multiply(plmM.inverse()))

    OX = App.Vector(1, 0, 0)
    OZ = App.Vector(0, 0, 1)

    base = m.multiply(placement.Base)
    xdir = m.submatrix(3).multiply(placement.Rotation.multVec(OX))
    zdir = m.submatrix(3).multiply(placement.Rotation.multVec(OZ))
    rot = makeOrientationFromLocalAxes(zdir, xdir)
    return App.Placement(base, rot)
예제 #3
0
    def derivedExecute(self, obj):
        self.assureGenerator(obj)
        self.assureProperties(obj)
        self.updateReadonlyness(obj)

        # Apply links
        if screen(obj.Link):
            if lattice2BaseFeature.isObjectLattice(screen(obj.Link)):
                lattice2Executer.warning(
                    obj,
                    "For polar array, axis link is expected to be a regular shape. Lattice objct was supplied instead, it's going to be treated as a generic shape."
                )

            #resolve the link
            if len(obj.LinkSubelement) > 0:
                linkedShape = screen(obj.Link).Shape.getElement(
                    obj.LinkSubelement)
            else:
                linkedShape = screen(obj.Link).Shape

            #Type check
            if linkedShape.ShapeType != 'Edge':
                raise ValueError('Axis link must be an edge; it is ' +
                                 linkedShape.ShapeType + ' instead.')
            if type(linkedShape.Curve) is not Part.Line:
                raise ValueError('Axis link must be a line; it is ' +
                                 type(linkedShape.Curve) + ' instead.')

            #obtain
            start_point = linkedShape.valueAt(linkedShape.FirstParameter)
            end_point = linkedShape.valueAt(linkedShape.LastParameter)
            dir = end_point - start_point
            point = start_point if not obj.Reverse else end_point

            if obj.DirIsDriven:
                obj.Dir = dir
            if obj.PointIsDriven:
                obj.Point = point
            if obj.DrivenProperty != 'None':
                if obj.DrivenProperty == 'Span':
                    propname = "SpanEnd"
                    obj.SpanEnd = obj.SpanStart + App.Units.Quantity(
                        'mm') * dir.Length
                else:
                    propname = obj.DrivenProperty
                    setattr(obj, propname, dir.Length)
                if self.generator.isPropertyControlledByGenerator(propname):
                    lattice2Executer.warning(
                        obj, "Property " + propname +
                        " is driven by both generator and link. Generator has priority."
                    )

        # Generate series of values
        self.generator.execute()
        values = [float(strv) for strv in obj.Values]

        #Apply reversal
        if obj.Reverse:
            obj.Dir = obj.Dir * (-1.0)
            if not (obj.DirIsDriven and screen(obj.Link)):
                obj.Reverse = False

        # precompute orientation
        if obj.OrientMode == 'Along axis':
            ori = lattice2GeomUtils.makeOrientationFromLocalAxes(
                ZAx=obj.Dir).multiply(
                    lattice2GeomUtils.makeOrientationFromLocalAxes(
                        ZAx=App.Vector(1, 0, 0), XAx=App.Vector(0, 0, 1)))
        else:
            ori = App.Rotation()

        dir = obj.Dir
        dir.normalize()

        # Make the array
        output = []  # list of placements
        for v in values:
            output.append(App.Placement(obj.Point + obj.Dir * v, ori))

        return output
예제 #4
0
    def derivedExecute(self, obj):
        base_is_lattice = LBF.isObjectLattice(obj.Object)
        pivot_is_lattice = LBF.isObjectLattice(
            obj.Pivot[0]) if obj.Pivot else True
        flipX = obj.FlipX
        flipY = obj.FlipY
        flipZ = obj.FlipZ

        # collect mirror pivot placements
        pivots = None
        em = 0  #editormode of PivotPlacement property. 0 = editable, 1 = read-only, 2 = hidden
        if obj.Pivot:
            em = 1  #read-only
            if pivot_is_lattice:
                pivots = LBF.getPlacementsList(obj.Pivot[0])
            else:
                pivot_shape = resolveSingleSublink(obj.Pivot)
                if pivot_shape.ShapeType == 'Edge' and type(
                        pivot_shape.Curve) is Part.Line:
                    dir = pivot_shape.Curve.Direction
                    base = pivot_shape.CenterOfMass
                    if flipX != flipY:
                        raise ValueError(
                            "Unsupported combination of flips for mirroring against line. FlipX and FlipY must either be both on or both off."
                        )
                    rot = makeOrientationFromLocalAxes(dir)
                    pivots = [App.Placement(base, rot)]
                elif pivot_shape.ShapeType == 'Face' and type(
                        pivot_shape.Surface) is Part.Plane:
                    dir = pivot_shape.Surface.Axis
                    base = pivot_shape.CenterOfMass
                    if flipX != flipY:
                        raise ValueError(
                            "Unsupported combination of flips for mirroring against line. FlipX and FlipY must either be both on or both off."
                        )
                    rot = makeOrientationFromLocalAxes(dir)
                    pivots = [App.Placement(base, rot)]
                elif pivot_shape.ShapeType == 'Vertex':
                    base = pivot_shape.Point
                    pivots = [App.Placement(base, obj.PivotPlacement.Rotation)]
                    em = 0  #editable
                else:
                    raise TypeError("Unsupported geometry for use as mirror")
            if len(pivots) == 1:
                obj.PivotPlacement = pivots[0]
            else:
                em = 2  #hidden
        else:
            pivots = [obj.PivotPlacement]
            em = 0
        obj.setEditorMode('PivotPlacement', em)

        # collect objects to be mirrored
        loop = False
        whole = obj.ObjectTraversal == 'Use whole'
        children = []
        if base_is_lattice:
            children = LBF.getPlacementsList(obj.Object)
        else:
            if obj.ObjectTraversal == 'Use whole':
                children = [obj.Object.Shape]
                loop = True
            elif obj.ObjectTraversal == 'Direct children only':
                children = obj.Object.Shape.childShapes()
            elif obj.ObjectTraversal == 'Use whole':
                children = LCE.AllLeaves(obj.Object.Shape)
            else:
                raise ValueError(
                    "Traversal mode not implemented: {mode}".format(
                        mode=obj.ObjectTraversal))

        if len(pivots) != len(children) and not loop and not whole:
            lattice2Executer.warning(
                obj,
                "{label}: Number of children ({nch}) doesn't match the number of pivot placements ({npiv})"
                .format(label=obj.Label, nch=len(children), npiv=len(pivots)))
            n = min(len(pivots), len(children))
        else:
            n = len(pivots)

        # actual mirroring!
        result = []
        for i in range(n):
            piv = pivots[i]
            ichild = i % len(children)
            if base_is_lattice:
                if whole:
                    for plm in children:
                        result.append(
                            mirrorPlacement(plm, piv, flipX, flipY, flipZ))
                else:
                    result.append(
                        mirrorPlacement(children[ichild], piv, flipX, flipY,
                                        flipZ))
            else:
                result.append(
                    mirrorShape(children[ichild], piv, flipX, flipY, flipZ))

        # write out the result
        if base_is_lattice:
            return result
        else:
            if n == 1:
                result = ShapeCopy.transformCopy(result[0])
            else:
                result = Part.Compound(result)
            obj.Shape = result
            return None
예제 #5
0
    def derivedExecute(self,obj):
        # cache stuff
        if lattice2BaseFeature.isObjectLattice(obj.ShapeLink):
            lattice2Executer.warning(obj,"ShapeLink points to a placement/array of placements. The placement/array will be reinterpreted as a generic shape; the results may be unexpected.")

        base = obj.ShapeLink.Shape
        if obj.CompoundTraversal == "Use as a whole":
            baseChildren = [base]
        else:
            if base.ShapeType != 'Compound':
                base = Part.makeCompound([base])
            if obj.CompoundTraversal == "Recursive":
                baseChildren = LCE.AllLeaves(base)
            else:
                baseChildren = base.childShapes()
        
                        
        #cache mode comparisons, for speed
        posIsNone = obj.TranslateMode == '(none)'
        posIsParent = obj.TranslateMode == 'parent'
        posIsChild = obj.TranslateMode == 'child'
        posIsCenterM = obj.TranslateMode == 'child.CenterOfMass'
        posIsCenterBB = obj.TranslateMode == 'child.CenterOfBoundBox'
        posIsVertex = obj.TranslateMode == 'child.Vertex'
        
        oriIsNone = obj.OrientMode == '(none)'
        oriIsParent = obj.OrientMode == 'parent'
        oriIsChild = obj.OrientMode == 'child'
        oriIsInertial = obj.OrientMode == 'child.InertiaAxes'
        oriIsEdge = obj.OrientMode == 'child.Edge'
        oriIsFace = obj.OrientMode == 'child.FaceAxis'
        
        # initialize output containers and loop variables
        outputPlms = [] #list of placements
        
        # the essence
        for child in baseChildren:
            pos = App.Vector()
            ori = App.Rotation()
            if posIsNone:
                pass
            elif posIsParent:
                pos = base.Placement.Base
            elif posIsChild:
                pos = child.Placement.Base
            elif posIsCenterM:
                leaves = LCE.AllLeaves(child)
                totalW = 0
                weightAttrib = {"Vertex":"",
                             "Edge":"Length",
                             "Wire":"Length",
                             "Face":"Area",
                             "Shell":"Area",
                             "Solid":"Volume",
                             "CompSolid":""}[leaves[0].ShapeType]
                #Center of mass of a compound is a weghted average of centers
                # of mass of individual objects.
                for leaf in leaves:
                    w = 1.0 if not weightAttrib else (getattr(leaf, weightAttrib))
                    if leaf.ShapeType == 'Vertex':
                        leafCM = leaf.Point
                    #elif child.ShapeType == 'CompSolid':
                        #todo
                    else: 
                        leafCM = leaf.CenterOfMass
                    pos += leafCM * w
                    totalW += w
                pos = pos * (1.0/totalW)
            elif posIsCenterBB:
                import lattice2BoundBox
                bb = lattice2BoundBox.getPrecisionBoundBox(child)
                pos = bb.Center
            elif posIsVertex:
                v = child.Vertexes[obj.TranslateElementIndex - 1]
                pos = v.Point
            else:
                raise ValueError(obj.Name + ": translation mode not implemented: "+obj.TranslateMode)
            
            if oriIsNone:
                pass
            elif oriIsParent:
                ori = base.Placement.Rotation
            elif oriIsChild:
                ori = child.Placement.Rotation
            elif oriIsInertial:
                leaves = LCE.AllLeaves(child)
                if len(leaves)>1:
                    raise ValueError(obj.Name + ": calculation of principal axes of compounds is not supported yet")
                props = leaves[0].PrincipalProperties
                XAx = props['FirstAxisOfInertia']
                ZAx = props['ThirdAxisOfInertia']
                ori = Utils.makeOrientationFromLocalAxes(ZAx, XAx)
            elif oriIsEdge:
                edge = child.Edges[obj.OrientElementIndex - 1]
                XAx = edge.Curve.tangent(edge.Curve.FirstParameter)[0]
                ori1 = Utils.makeOrientationFromLocalAxes(ZAx= XAx)
                ori2 = Utils.makeOrientationFromLocalAxes(ZAx= App.Vector(1,0,0),XAx= App.Vector(0,0,1))
                ori = ori1.multiply(ori2)
            elif oriIsFace:
                face = child.Faces[obj.OrientElementIndex - 1]
                ZAx = face.Surface.Axis
            else:
                raise ValueError(obj.Name + ": orientation mode not implemented: "+obj.OrientMode)

            plm = App.Placement(pos, ori)
            outputPlms.append(plm)
        return outputPlms
예제 #6
0
    def derivedExecute(self, obj):
        self.assureGenerator(obj)
        self.assureProperties(obj)
        self.updateReadonlyness(obj)

        # Apply links
        if screen(obj.AxisLink):
            if lattice2BaseFeature.isObjectLattice(screen(obj.AxisLink)):
                lattice2Executer.warning(
                    obj,
                    "For polar array, axis link is expected to be a regular shape. Lattice objct was supplied instead, it's going to be treated as a generic shape."
                )

            #resolve the link
            if len(obj.AxisLinkSubelement) > 0:
                linkedShape = screen(obj.AxisLink).Shape.getElement(
                    obj.AxisLinkSubelement)
            else:
                linkedShape = screen(obj.AxisLink).Shape

            #Type check
            if linkedShape.ShapeType != 'Edge':
                raise ValueError('Axis link must be an edge; it is ' +
                                 linkedShape.ShapeType + ' instead.')

            #prepare
            dir = App.Vector()
            point = App.Vector()
            if isinstance(linkedShape.Curve, Part.Line):
                start_point = linkedShape.valueAt(linkedShape.FirstParameter)
                end_point = linkedShape.valueAt(linkedShape.LastParameter)
                dir = end_point - start_point
                point = start_point
            elif isinstance(linkedShape.Curve, Part.Circle):
                dir = linkedShape.Curve.Axis
                point = linkedShape.Curve.Center
            else:
                raise ValueError(
                    "Edge " + repr(linkedShape) +
                    " can't be used to derive an axis. It must be either a line or a circle/arc."
                )

            #apply
            if obj.AxisDirIsDriven:
                obj.AxisDir = dir
            if obj.AxisPointIsDriven:
                obj.AxisPoint = point

        self.generator.execute()

        # cache properties into variables
        radius = float(obj.Radius)
        values = [float(strv) for strv in obj.Values]

        # compute initial vector. It is to be perpendicular to Axis
        rot_ini = lattice2GeomUtils.makeOrientationFromLocalAxes(
            ZAx=obj.AxisDir)
        overallPlacement = App.Placement(obj.AxisPoint, rot_ini)

        # Make the array
        output = []  # list of placements
        for ang in values:
            p = Part.Vertex()
            localrot = App.Rotation(App.Vector(0, 0, 1), ang)
            localtransl = localrot.multVec(App.Vector(radius, 0, 0))
            localplm = App.Placement(localtransl, localrot)
            resultplm = overallPlacement.multiply(localplm)
            if obj.OrientMode == 'None':
                resultplm.Rotation = App.Rotation()
            output.append(resultplm)

        return output
예제 #7
0
    def derivedExecute(self,obj):
        self.assureGenerator(obj)
        self.updateReadonlyness(obj)

        # Apply links
        if obj.Link:
            if lattice2BaseFeature.isObjectLattice(obj.Link):
                lattice2Executer.warning(obj,"For polar array, axis link is expected to be a regular shape. Lattice objct was supplied instead, it's going to be treated as a generic shape.")
            
            #resolve the link
            if len(obj.LinkSubelement) > 0:
                linkedShape = obj.Link.Shape.getElement(obj.LinkSubelement)
            else:
                linkedShape = obj.Link.Shape
            
            #Type check
            if linkedShape.ShapeType != 'Edge':
                raise ValueError('Axis link must be an edge; it is '+linkedShape.ShapeType+' instead.')
            if type(linkedShape.Curve) is not Part.Line:
                raise ValueError('Axis link must be a line; it is '+type(linkedShape.Curve)+' instead.')
            
            #obtain
            dir = linkedShape.Curve.EndPoint - linkedShape.Curve.StartPoint
            point = linkedShape.Curve.StartPoint if not obj.Reverse else linkedShape.Curve.EndPoint
            
            if obj.DirIsDriven:
                obj.Dir = dir
            if obj.PointIsDriven:
                obj.Point = point
            if obj.DrivenProperty != 'None':
                if obj.DrivenProperty == 'Span':
                    propname = "SpanEnd"
                    obj.SpanEnd = obj.SpanStart + App.Units.Quantity('mm')*dir.Length
                else:
                    propname = obj.DrivenProperty
                    setattr(obj, propname, dir.Length)
                if self.generator.isPropertyControlledByGenerator(propname):
                    lattice2Executer.warning(obj, "Property "+propname+" is driven by both generator and link. Generator has priority.")

        
        # Generate series of values
        self.generator.execute()
        values = [float(strv) for strv in obj.Values]
        
        #Apply reversal
        if obj.Reverse:
            obj.Dir = obj.Dir*(-1.0)
            if not(obj.DirIsDriven and obj.Link):
                obj.Reverse = False

        # precompute orientation
        if obj.OrientMode == 'Along axis':
            ori = lattice2GeomUtils.makeOrientationFromLocalAxes(ZAx= obj.Dir).multiply(
                    lattice2GeomUtils.makeOrientationFromLocalAxes(ZAx= App.Vector(1,0,0), XAx= App.Vector(0,0,1)) )
        else:
            ori = App.Rotation()
        
        dir = obj.Dir
        dir.normalize()
        
        # Make the array
        output = [] # list of placements
        for v in values:
            output.append( App.Placement(obj.Point + obj.Dir*v, ori) )
            
        return output
예제 #8
0
    def derivedExecute(self,obj):
        # cache stuff
        if lattice2BaseFeature.isObjectLattice(screen(obj.ShapeLink)):
            lattice2Executer.warning(obj,"ShapeLink points to a placement/array of placements. The placement/array will be reinterpreted as a generic shape; the results may be unexpected.")

        base = screen(obj.ShapeLink).Shape
        if obj.CompoundTraversal == "Use as a whole":
            baseChildren = [base]
        else:
            if base.ShapeType != 'Compound':
                base = Part.makeCompound([base])
            if obj.CompoundTraversal == "Recursive":
                baseChildren = LCE.AllLeaves(base)
            else:
                baseChildren = base.childShapes()
        
                        
        #cache mode comparisons, for speed
        posIsNone = obj.TranslateMode == '(none)'
        posIsParent = obj.TranslateMode == 'parent'
        posIsChild = obj.TranslateMode == 'child'
        posIsCenterM = obj.TranslateMode == 'child.CenterOfMass'
        posIsCenterBB = obj.TranslateMode == 'child.CenterOfBoundBox'
        posIsVertex = obj.TranslateMode == 'child.Vertex'
        
        oriIsNone = obj.OrientMode == '(none)'
        oriIsParent = obj.OrientMode == 'parent'
        oriIsChild = obj.OrientMode == 'child'
        oriIsInertial = obj.OrientMode == 'child.InertiaAxes'
        oriIsEdge = obj.OrientMode == 'child.Edge'
        oriIsFace = obj.OrientMode == 'child.FaceAxis'
        
        # initialize output containers and loop variables
        outputPlms = [] #list of placements
        
        # the essence
        for child in baseChildren:
            pos = App.Vector()
            ori = App.Rotation()
            if posIsNone:
                pass
            elif posIsParent:
                pos = base.Placement.Base
            elif posIsChild:
                pos = child.Placement.Base
            elif posIsCenterM:
                leaves = LCE.AllLeaves(child)
                totalW = 0
                weightAttrib = {"Vertex":"",
                             "Edge":"Length",
                             "Wire":"Length",
                             "Face":"Area",
                             "Shell":"Area",
                             "Solid":"Volume",
                             "CompSolid":""}[leaves[0].ShapeType]
                #Center of mass of a compound is a weghted average of centers
                # of mass of individual objects.
                for leaf in leaves:
                    w = 1.0 if not weightAttrib else (getattr(leaf, weightAttrib))
                    if leaf.ShapeType == 'Vertex':
                        leafCM = leaf.Point
                    #elif child.ShapeType == 'CompSolid':
                        #todo
                    else: 
                        leafCM = leaf.CenterOfMass
                    pos += leafCM * w
                    totalW += w
                pos = pos * (1.0/totalW)
            elif posIsCenterBB:
                import lattice2BoundBox
                bb = lattice2BoundBox.getPrecisionBoundBox(child)
                pos = bb.Center
            elif posIsVertex:
                v = child.Vertexes[obj.TranslateElementIndex - 1]
                pos = v.Point
            else:
                raise ValueError(obj.Name + ": translation mode not implemented: "+obj.TranslateMode)
            
            if oriIsNone:
                pass
            elif oriIsParent:
                ori = base.Placement.Rotation
            elif oriIsChild:
                ori = child.Placement.Rotation
            elif oriIsInertial:
                leaves = LCE.AllLeaves(child)
                if len(leaves)>1:
                    raise ValueError(obj.Name + ": calculation of principal axes of compounds is not supported yet")
                props = leaves[0].PrincipalProperties
                XAx = props['FirstAxisOfInertia']
                ZAx = props['ThirdAxisOfInertia']
                ori = Utils.makeOrientationFromLocalAxes(ZAx, XAx)
            elif oriIsEdge:
                edge = child.Edges[obj.OrientElementIndex - 1]
                XAx = edge.Curve.tangent(edge.Curve.FirstParameter)[0]
                ori1 = Utils.makeOrientationFromLocalAxes(ZAx= XAx)
                ori2 = Utils.makeOrientationFromLocalAxes(ZAx= App.Vector(1,0,0),XAx= App.Vector(0,0,1))
                ori = ori1.multiply(ori2)
            elif oriIsFace:
                face = child.Faces[obj.OrientElementIndex - 1]
                ZAx = face.Surface.Axis
            else:
                raise ValueError(obj.Name + ": orientation mode not implemented: "+obj.OrientMode)

            plm = App.Placement(pos, ori)
            outputPlms.append(plm)
        return outputPlms