def derivedExecute(self,obj):
        self.updateReadOnlyness(obj)

        # Apply links
        if obj.Link:
            if latticeBaseFeature.isObjectLattice(obj.Link):
                latticeExecuter.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':
                    obj.SpanEnd = obj.SpanStart + App.Units.Quantity('mm')*dir.Length
                else:
                    setattr(obj, obj.DrivenProperty, dir.Length)

        # Fill in (update read-only) properties that are driven by the mode.
        if obj.Mode == 'SpanN':
            n = obj.NumberLinear
            if obj.EndInclusive:
                n -= 1
            if n == 0:
                n = 1
            obj.Step = (obj.SpanEnd - obj.SpanStart)/n
            if obj.DrivenProperty == 'Step' and obj.Link:
                latticeExecuter.warning(obj,"Step property is being driven by both the link and the selected mode. Mode has priority.")
        elif obj.Mode == 'StepN':
            n = obj.NumberLinear
            if obj.EndInclusive:
                n -= 1
            obj.SpanEnd = obj.SpanStart + obj.Step*n
            if 'Span' in obj.DrivenProperty and obj.Link:
                latticeExecuter.warning(obj,"SpanEnd property is being driven by both the link and the selected mode. Mode has priority.")
        elif obj.Mode == 'SpanStep':
            nfloat = float((obj.SpanEnd - obj.SpanStart) / obj.Step)
            n = math.trunc(nfloat - ParaConfusion) + 1
            if obj.EndInclusive and abs(nfloat-round(nfloat)) <= ParaConfusion:
                n = n + 1
            obj.NumberLinear = n
            
        
        # Generate the actual array. We can use Step and N directly to 
        # completely avoid mode logic, since we had updated them
        
        # cache properties into variables
        step = float(obj.Step)
        start = float(obj.SpanStart) + step*float(obj.Offset)
        n = int(obj.NumberLinear)
        
        #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 = latticeGeomUtils.makeOrientationFromLocalAxes(ZAx= obj.Dir).multiply(
                    latticeGeomUtils.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
        if obj.Mode != "Spreadsheet":
            for i in range(0, n):
                position = start + step*i
                output.append( App.Placement(obj.Point + obj.Dir*position, ori) )
        else:
            #parse address
            addr = obj.CellStart
            #assuming only two letter column
            if addr[1].isalpha():
                col = addr[0:2]
                row = addr[2:]
            else:
                col = addr[0:1]
                row = addr[1:]
            row = int(row)
            
            #loop until the value can't be read out
            while True:
                try:
                    position = obj.SpreadSheet.get(col+str(row))
                except ValueError:
                    break
                position = float(position)
                output.append( App.Placement(obj.Point + obj.Dir*position, ori) )
                row += 1
            
        return output
    def derivedExecute(self,obj):
        # Fill in (update read-only) properties that are driven by the mode.
        self.updateReadOnlyness(obj)
        if obj.Mode == 'SpanN':
            n = obj.NumberPolar
            if obj.EndInclusive:
                n -= 1
            if n == 0:
                n = 1
            obj.AngleStep = (obj.AngleSpanEnd - obj.AngleSpanStart)/n
        elif obj.Mode == 'StepN':
            n = obj.NumberPolar
            if obj.EndInclusive:
                n -= 1
            obj.AngleSpanEnd = obj.AngleSpanStart + obj.AngleStep*n
        elif obj.Mode == 'SpanStep':
            nfloat = float((obj.AngleSpanEnd - obj.AngleSpanStart) / obj.AngleStep)
            n = math.trunc(nfloat - ParaConfusion) + 1
            if obj.EndInclusive and abs(nfloat-round(nfloat)) <= ParaConfusion:
                n = n + 1
            obj.NumberPolar = n
            
        # Apply links
        if obj.AxisLink:
            if latticeBaseFeature.isObjectLattice(obj.AxisLink):
                latticeExecuter.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
        
        # Generate the actual array. We can use Step and N directly to 
        # completely avoid mode logic, since we had updated them
        
        # cache properties into variables
        step = float(obj.AngleStep)
        startAng = float(obj.AngleSpanStart) + step*float(obj.Offset)
        n = int(obj.NumberPolar)
        radius = float(obj.Radius)
        
        # compute initial vector. It is to be perpendicular to Axis
        rot_ini = latticeGeomUtils.makeOrientationFromLocalAxes(ZAx= obj.AxisDir)
        overallPlacement = App.Placement(obj.AxisPoint, rot_ini)
        
        # Make the array
        output = [] # list of placements
        if obj.Mode != "Spreadsheet":
            for i in range(0, n):
                ang = startAng + step*i
                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)
        else:
            #parse address
            addr = obj.CellStart
            #assuming only two letter column
            if addr[1].isalpha():
                col = addr[0:2]
                row = addr[2:]
            else:
                col = addr[0:1]
                row = addr[1:]
            row = int(row)
            
            #loop until the value an't be read out
            while True:
                try:
                    ang = obj.SpreadSheet.get(col+str(row))
                except ValueError:
                    break
                ang = float(ang)
                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)
                output.append( overallPlacement.multiply(localplm) )
                row += 1
            
        return output
Esempio n. 3
0
    def derivedExecute(self,obj):
        # cache stuff
        if latticeBaseFeature.isObjectLattice(obj.Base):
            latticeExecuter.warning(obj,"Base is a lattice object. Since a non-lattice object is required by arrayFromShape tool, the results may be unexpected.")

        base = obj.Base.Shape
        if obj.WholeObject:
            baseChildren = [base]
            #if obj.FlattenBaseHierarchy:
            #    latticeExecuter.warning(obj, "FlattenBaseHierarchy is ignored because WholeObject is set to True")
        else:
            if base.ShapeType != 'Compound':
                base = Part.makeCompound([base])
            if obj.FlattenBaseHierarchy:
                baseChildren = LCE.AllLeaves(base)
            else:
                baseChildren = base.childShapes()
        
                        
        #cache mode comparisons, for speed
        posIsNone = obj.TranslateMode == '(none)'
        posIsBase = obj.TranslateMode == 'base'
        posIsChild = obj.TranslateMode == 'child'
        posIsCenterM = obj.TranslateMode == 'child.CenterOfMass'
        posIsCenterBB = obj.TranslateMode == 'child.CenterOfBoundBox'
        posIsVertex = obj.TranslateMode == 'child.Vertex'
        
        oriIsNone = obj.OrientMode == '(none)'
        oriIsBase = obj.OrientMode == 'base'
        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 posIsBase:
                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 latticeBoundBox
                bb = latticeBoundBox.getPrecisionBoundBox(child)
                pos = bb.Center
            elif posIsVertex:
                v = child.Vertexes[obj.TranslateElementIndex - 1]
                pos = v.Point
            else:
                raise ValueError("latticePolarArrayFromShape: translation mode not implemented: "+obj.TranslateMode)
            
            if oriIsNone:
                pass
            elif oriIsBase:
                ori = base.Placement.Rotation
            elif oriIsChild:
                ori = child.Placement.Rotation
            elif oriIsInertial:
                leaves = LCE.AllLeaves(child)
                if len(leaves)>1:
                    raise ValueError("latticePolarArrayFromShape: 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("latticePolarArrayFromShape: rientation mode not implemented: "+obj.OrientMode)

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