def derivedExecute(self,obj): self.assureProperties(obj) # cache stuff objectShape = obj.Object.Shape placements = lattice2BaseFeature.getPlacementsList(obj.PlacementsTo, obj) outputIsLattice = lattice2BaseFeature.isObjectLattice(obj.Object) # Pre-collect base placement list, if base is a lattice. For speed. if outputIsLattice: objectPlms = lattice2BaseFeature.getPlacementsList(obj.Object,obj) placements = DereferenceArray(obj, placements, obj.PlacementsFrom, obj.Referencing) # initialize output containers and loop variables outputShapes = [] #output list of shapes outputPlms = [] #list of placements copy_method_index = ShapeCopy.getCopyTypeIndex(obj.Copying) # the essence for plm in placements: if outputIsLattice: for objectPlm in objectPlms: outputPlms.append(plm.multiply(objectPlm)) else: outputShape = ShapeCopy.copyShape(objectShape, copy_method_index, plm) #outputShape.Placement = plm.multiply(outputShape.Placement) # now handled by copyShape outputShapes.append(outputShape) if outputIsLattice: return outputPlms else: # Output shape or compound (complex logic involving OutputCompounding property) #first, autosettle the OutputCompounding. if obj.OutputCompounding == "(autosettle)": if hasattr(obj.PlacementsTo,"ExposePlacement") and obj.PlacementsTo.ExposePlacement == False: obj.OutputCompounding = "always" else: obj.OutputCompounding = "only if many" #now, set the result shape if len(outputShapes) == 1 and obj.OutputCompounding == "only if many": sh = outputShapes[0] sh = ShapeCopy.transformCopy(sh) obj.Shape = sh else: obj.Shape = Part.makeCompound(outputShapes) return None
def derivedExecute(self,obj): self.assureProperties(obj) # cache stuff objectShape = screen(obj.Object).Shape placements = lattice2BaseFeature.getPlacementsList(screen(obj.PlacementsTo), obj) outputIsLattice = lattice2BaseFeature.isObjectLattice(screen(obj.Object)) # Pre-collect base placement list, if base is a lattice. For speed. if outputIsLattice: objectPlms = lattice2BaseFeature.getPlacementsList(screen(obj.Object),obj) placements = DereferenceArray(obj, placements, screen(obj.PlacementsFrom), obj.Referencing) # initialize output containers and loop variables outputShapes = [] #output list of shapes outputPlms = [] #list of placements copy_method_index = ShapeCopy.getCopyTypeIndex(obj.Copying) # the essence for plm in placements: if outputIsLattice: for objectPlm in objectPlms: outputPlms.append(plm.multiply(objectPlm)) else: outputShape = ShapeCopy.copyShape(objectShape, copy_method_index, plm) #outputShape.Placement = plm.multiply(outputShape.Placement) # now handled by copyShape outputShapes.append(outputShape) if outputIsLattice: return outputPlms else: # Output shape or compound (complex logic involving OutputCompounding property) #first, autosettle the OutputCompounding. if obj.OutputCompounding == "(autosettle)": if hasattr(screen(obj.PlacementsTo),"ExposePlacement") and screen(obj.PlacementsTo).ExposePlacement == False: obj.OutputCompounding = "always" else: obj.OutputCompounding = "only if many" #now, set the result shape if len(outputShapes) == 1 and obj.OutputCompounding == "only if many": sh = outputShapes[0] sh = ShapeCopy.transformCopy(sh) obj.Shape = sh else: obj.Shape = Part.makeCompound(outputShapes) return None
def execute(self,selfobj): #validity check if isObjectLattice(selfobj.Object): import lattice2Executer lattice2Executer.warning(selfobj,"A generic shape is expected, but a placement/array was supplied. It will be treated as a generic shape.") rst = [] #variable to receive the final list of shapes lnkobj = selfobj.Object for subname in selfobj.SubNames: subname = subname.strip() if len(subname)==0: raise ValueError("Empty subname! Not allowed.") if 'Face' in subname: index = int(subname.replace('Face',''))-1 rst.append(lnkobj.Shape.Faces[index]) elif 'Edge' in subname: index = int(subname.replace('Edge',''))-1 rst.append(lnkobj.Shape.Edges[index]) elif 'Vertex' in subname: index = int(subname.replace('Vertex',''))-1 rst.append(lnkobj.Shape.Vertexes[index]) else: lattice2Executer.warning(selfobj,"Unexpected subelement name: "+subname+". Trying to extract it with .Shape.getElement()...") rst.append(linkobj.Shape.getElement(subname)) if len(rst) == 0: scale = 1.0 try: if selfobj.Object: scale = selfobj.Object[0].Shape.BoundBox.DiagonalLength/math.sqrt(3) except Exception as err: App.Console.PrintError(selfobj.Name+": Failed to estimate size of marker shape") if scale < DistConfusion * 100: scale = 1.0 selfobj.Shape = markers.getNullShapeShape(scale) raise ValueError('Nothing is linked, apparently!') #Feeding empty compounds to FreeCAD seems to cause rendering issues, otherwise it would have been a good idea to output nothing. if len(rst) > 1: selfobj.Shape = Part.makeCompound(rst) else: # don't make compound of one shape, output it directly sh = rst[0] # absorb placement of original shape sh = ShapeCopy.transformCopy(sh) # apply Placement that is filled into feature's Placement property (not necessary) sh.Placement = selfobj.Placement selfobj.Shape = sh
def execute(self, selfobj): self.assureProperties(selfobj) #validity check if isObjectLattice(screen(selfobj.Object)): import lattice2Executer lattice2Executer.warning( selfobj, "A generic shape is expected, but a placement/array was supplied. It will be treated as a generic shape." ) lnkobj = screen(selfobj.Object) sh = lnkobj.Shape # subsequencing full_link = (lnkobj, selfobj.SubNames) if selfobj.Looping == 'Single': lnkseq = [full_link] else: lnkseq = LSS.Subsequence_auto(full_link, selfobj.CompoundTraversal, selfobj.Looping) # main code seq_packs = [ ] #pack = single item of subsequence. Pack contains list of elements that were selected. shape_count = 0 for lnk in lnkseq: # loop over subsequence (if Looping == 'Single', this loop will only loop once) # extract the pack assert ( lnk[0] is lnkobj ) # all links should point to elements of one object anyway subnames = lnk[1] pack = [ ] #acculumator, to eventually become a compound of shapes for this subsequence item for subname in subnames: subname = subname.strip() if len(subname) == 0: raise ValueError("Empty subname! Not allowed.") if 'Face' in subname: # manual handling of standard cases, because support for negative indexing is needed index = int(subname.replace('Face', '')) - 1 pack.append(sh.Faces[index]) elif 'Edge' in subname: index = int(subname.replace('Edge', '')) - 1 pack.append(sh.Edges[index]) elif 'Vertex' in subname: index = int(subname.replace('Vertex', '')) - 1 pack.append(sh.Vertexes[index]) else: #fail-safe. non-standard sublink. import lattice2Executer lattice2Executer.warning( selfobj, "Unexpected subelement name: " + subname + ". Trying to extract it with .Shape.getElement()...") pack.append(sh.getElement(subname)) shape_count += len(pack) # convert list into compound if len(pack) == 1: pack = ShapeCopy.transformCopy(pack[0]) else: pack = Part.makeCompound(pack) # accumulate seq_packs.append(pack) # convert list into compound if len(seq_packs) == 1: seq_packs = seq_packs[0] else: seq_packs = Part.makeCompound(seq_packs) if shape_count == 0: # no shapes collected, FAIL! scale = 1.0 try: if screen(selfobj.Object): scale = screen( selfobj.Object ).Shape.BoundBox.DiagonalLength / math.sqrt(3) except Exception as err: App.Console.PrintError( selfobj.Name + ": Failed to estimate size of marker shape") if scale < DistConfusion * 100: scale = 1.0 selfobj.Shape = markers.getNullShapeShape(scale) raise ValueError( 'Nothing is linked, apparently!' ) #Feeding empty compounds to FreeCAD seems to cause rendering issues, otherwise it would have been a good idea to output nothing. # done! selfobj.Shape = seq_packs
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
def execute(self, obj): #validity check if isObjectLattice(screen(obj.Base)): import lattice2Executer lattice2Executer.warning( obj, "A generic shape is expected, but an array of placements was supplied. It will be treated as a generic shape." ) rst = [] #variable to receive the final list of shapes shps = screen(obj.Base).Shape.childShapes() if obj.FilterType == 'bypass': rst = shps elif obj.FilterType == 'specific items': rst = [] flags = [False] * len(shps) ranges = obj.items.split(';') for r in ranges: r_v = r.split(':') if len(r_v) == 1: i = int(r_v[0]) rst.append(shps[i]) flags[i] = True elif len(r_v) == 2 or len(r_v) == 3: if len(r_v) == 2: r_v.append( "" ) # fix issue #1: instead of checking length here and there, simply add the missing field =) ifrom = None if len(r_v[0].strip()) == 0 else int(r_v[0]) ito = None if len(r_v[1].strip()) == 0 else int(r_v[1]) istep = None if len(r_v[2].strip()) == 0 else int(r_v[2]) rst = rst + shps[ifrom:ito:istep] for b in flags[ifrom:ito:istep]: b = True else: raise ValueError('index range cannot be parsed:' + r) if obj.Invert: rst = [] for i in range(0, len(shps)): if not flags[i]: rst.append(shps[i]) elif obj.FilterType == 'collision-pass': stencil = screen(obj.Stencil).Shape for s in shps: d = s.distToShape(stencil) if bool(d[0] < DistConfusion) ^ bool(obj.Invert): rst.append(s) elif obj.FilterType == 'window-volume' or obj.FilterType == 'window-area' or obj.FilterType == 'window-length' or obj.FilterType == 'window-distance': vals = [0.0] * len(shps) for i in range(0, len(shps)): if obj.FilterType == 'window-volume': vals[i] = shps[i].Volume elif obj.FilterType == 'window-area': vals[i] = shps[i].Area elif obj.FilterType == 'window-length': vals[i] = shps[i].Length elif obj.FilterType == 'window-distance': vals[i] = shps[i].distToShape(obj.Stencil.Shape)[0] maxval = max(vals) if obj.Stencil: if obj.FilterType == 'window-volume': maxval = obj.Stencil.Shape.Volume elif obj.FilterType == 'window-area': maxval = obj.Stencil.Shape.Area elif obj.FilterType == 'window-length': maxval = obj.Stencil.Shape.Length if obj.OverrideMaxVal: maxval = obj.OverrideMaxVal valFrom = obj.WindowFrom / 100.0 * maxval valTo = obj.WindowTo / 100.0 * maxval for i in range(0, len(shps)): if bool(vals[i] >= valFrom and vals[i] <= valTo) ^ obj.Invert: rst.append(shps[i]) else: raise ValueError('Filter mode not implemented:' + obj.FilterType) if len(rst) == 0: scale = 1.0 if not screen(obj.Base).Shape.isNull(): scale = screen( obj.Base).Shape.BoundBox.DiagonalLength / math.sqrt( 3) / math.sqrt(len(shps)) if scale < DistConfusion * 100: scale = 1.0 obj.Shape = markers.getNullShapeShape(scale) raise ValueError( 'Nothing passes through the filter' ) #Feeding empty compounds to FreeCAD seems to cause rendering issues, otherwise it would have been a good idea to output nothing. if len(rst) > 1: obj.Shape = Part.makeCompound(rst) else: # don't make compound of one shape, output it directly sh = rst[0] sh = ShapeCopy.transformCopy(sh) sh.Placement = obj.Placement obj.Shape = sh return
def execute(self,obj): #validity check if isObjectLattice(obj.Base): import lattice2Executer lattice2Executer.warning(obj,"A generic shape is expected, but an array of placements was supplied. It will be treated as a generic shape.") rst = [] #variable to receive the final list of shapes shps = obj.Base.Shape.childShapes() if obj.FilterType == 'bypass': rst = shps elif obj.FilterType == 'specific items': rst = [] flags = [False] * len(shps) ranges = obj.items.split(';') for r in ranges: r_v = r.split(':') if len(r_v) == 1: i = int(r_v[0]) rst.append(shps[i]) flags[i] = True elif len(r_v) == 2 or len(r_v) == 3: if len(r_v) == 2: r_v.append("") # fix issue #1: instead of checking length here and there, simply add the missing field =) ifrom = None if len(r_v[0].strip()) == 0 else int(r_v[0]) ito = None if len(r_v[1].strip()) == 0 else int(r_v[1]) istep = None if len(r_v[2].strip()) == 0 else int(r_v[2]) rst=rst+shps[ifrom:ito:istep] for b in flags[ifrom:ito:istep]: b = True else: raise ValueError('index range cannot be parsed:'+r) if obj.Invert : rst = [] for i in xrange(0,len(shps)): if not flags[i]: rst.append(shps[i]) elif obj.FilterType == 'collision-pass': stencil = obj.Stencil.Shape for s in shps: d = s.distToShape(stencil) if bool(d[0] < DistConfusion) ^ bool(obj.Invert): rst.append(s) elif obj.FilterType == 'window-volume' or obj.FilterType == 'window-area' or obj.FilterType == 'window-length' or obj.FilterType == 'window-distance': vals = [0.0] * len(shps) for i in xrange(0,len(shps)): if obj.FilterType == 'window-volume': vals[i] = shps[i].Volume elif obj.FilterType == 'window-area': vals[i] = shps[i].Area elif obj.FilterType == 'window-length': vals[i] = shps[i].Length elif obj.FilterType == 'window-distance': vals[i] = shps[i].distToShape(obj.Stencil.Shape)[0] maxval = max(vals) if obj.Stencil: if obj.FilterType == 'window-volume': maxval = obj.Stencil.Shape.Volume elif obj.FilterType == 'window-area': maxval = obj.Stencil.Shape.Area elif obj.FilterType == 'window-length': maxval = obj.Stencil.Shape.Length if obj.OverrideMaxVal: maxval = obj.OverrideMaxVal valFrom = obj.WindowFrom / 100.0 * maxval valTo = obj.WindowTo / 100.0 * maxval for i in xrange(0,len(shps)): if bool(vals[i] >= valFrom and vals[i] <= valTo) ^ obj.Invert: rst.append(shps[i]) else: raise ValueError('Filter mode not implemented:'+obj.FilterType) if len(rst) == 0: scale = 1.0 if not obj.Base.Shape.isNull(): scale = obj.Base.Shape.BoundBox.DiagonalLength/math.sqrt(3)/math.sqrt(len(shps)) if scale < DistConfusion * 100: scale = 1.0 print scale obj.Shape = markers.getNullShapeShape(scale) raise ValueError('Nothing passes through the filter') #Feeding empty compounds to FreeCAD seems to cause rendering issues, otherwise it would have been a good idea to output nothing. if len(rst) > 1: obj.Shape = Part.makeCompound(rst) else: # don't make compound of one shape, output it directly sh = rst[0] sh = ShapeCopy.transformCopy(sh) sh.Placement = obj.Placement obj.Shape = sh return