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
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