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
Example #2
0
    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
Example #3
0
    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
Example #4
0
    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
Example #5
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
Example #6
0
    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
Example #7
0
    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