Пример #1
0
def rotate(objectslist, angle, center=App.Vector(0,0,0),
           axis=App.Vector(0,0,1), copy=False):
    """rotate(objects,angle,[center,axis,copy])

    Rotates the objects contained in objects (that can be a list of objects
    or an object) of the given angle (in degrees) around the center, using
    axis as a rotation axis.

    Parameters
    ----------
    objectlist : list

    angle : list

    center : Base.Vector

    axis : Base.Vector
        If axis is omitted, the rotation will be around the vertical Z axis.

    copy : bool
        If copy is True, the actual objects are not moved, but copies
        are created instead.

    Return
    ----------
    The objects (or their copies) are returned.
    """
    import Part
    utils.type_check([(copy,bool)], "rotate")
    if not isinstance(objectslist,list):
        objectslist = [objectslist]

    objectslist.extend(groups.get_movable_children(objectslist))
    newobjlist = []
    newgroups = {}
    objectslist = utils.filter_objects_for_modifiers(objectslist, copy)

    for obj in objectslist:
        newobj = None
        # real_center and real_axis are introduced to take into account
        # the possibility that object is inside an App::Part
        if hasattr(obj, "getGlobalPlacement"):
            ci = obj.getGlobalPlacement().inverse().multVec(center)
            real_center = obj.Placement.multVec(ci)
            ai = obj.getGlobalPlacement().inverse().Rotation.multVec(axis)
            real_axis = obj.Placement.Rotation.multVec(ai)
        else:
            real_center = center
            real_axis = axis

        if copy:
            newobj = make_copy.make_copy(obj)
        else:
            newobj = obj
        if obj.isDerivedFrom("App::Annotation"):
            # TODO: this is very different from how move handle annotations
            # maybe we can uniform the two methods
            if axis.normalize() == App.Vector(1,0,0):
                newobj.ViewObject.RotationAxis = "X"
                newobj.ViewObject.Rotation = angle
            elif axis.normalize() == App.Vector(0,1,0):
                newobj.ViewObject.RotationAxis = "Y"
                newobj.ViewObject.Rotation = angle
            elif axis.normalize() == App.Vector(0,-1,0):
                newobj.ViewObject.RotationAxis = "Y"
                newobj.ViewObject.Rotation = -angle
            elif axis.normalize() == App.Vector(0,0,1):
                newobj.ViewObject.RotationAxis = "Z"
                newobj.ViewObject.Rotation = angle
            elif axis.normalize() == App.Vector(0,0,-1):
                newobj.ViewObject.RotationAxis = "Z"
                newobj.ViewObject.Rotation = -angle
        elif utils.get_type(obj) == "Point":
            v = App.Vector(obj.X,obj.Y,obj.Z)
            rv = v.sub(real_center)
            rv = DraftVecUtils.rotate(rv, math.radians(angle), real_axis)
            v = real_center.add(rv)
            newobj.X = v.x
            newobj.Y = v.y
            newobj.Z = v.z
        elif obj.isDerivedFrom("App::DocumentObjectGroup"):
            pass
        elif hasattr(obj,"Placement"):
            #FreeCAD.Console.PrintMessage("placement rotation\n")
            shape = Part.Shape()
            shape.Placement = obj.Placement
            shape.rotate(DraftVecUtils.tup(real_center), DraftVecUtils.tup(real_axis), angle)
            newobj.Placement = shape.Placement
        elif hasattr(obj,'Shape') and (utils.get_type(obj) not in ["WorkingPlaneProxy","BuildingPart"]):
            #think it make more sense to try first to rotate placement and later to try with shape. no?
            shape = obj.Shape.copy()
            shape.rotate(DraftVecUtils.tup(real_center), DraftVecUtils.tup(real_axis), angle)
            newobj.Shape = shape
        if copy:
            gui_utils.formatObject(newobj,obj)
        if newobj is not None:
            newobjlist.append(newobj)
        if copy:
            for p in obj.InList:
                if p.isDerivedFrom("App::DocumentObjectGroup") and (p in objectslist):
                    g = newgroups.setdefault(p.Name, App.ActiveDocument.addObject(p.TypeId, p.Name))
                    g.addObject(newobj)
                    break

    gui_utils.select(newobjlist)
    if len(newobjlist) == 1:
        return newobjlist[0]
    return newobjlist
Пример #2
0
def scale(objectslist,
          scale=App.Vector(1, 1, 1),
          center=App.Vector(0, 0, 0),
          copy=False):
    """scale(objects, scale, [center], copy)
    
    Scales the objects contained in objects (that can be a list of objects or 
    an object) of the given  around given center. 

    Parameters
    ----------
    objectlist : list

    scale : Base.Vector
        Scale factors defined by a given vector (in X, Y, Z directions).

    objectlist : Base.Vector
        Center of the scale operation.

    copy : bool
        If copy is True, the actual objects are not scaled, but copies
        are created instead. 

    Return
    ----------
    The objects (or their copies) are returned.
    """
    if not isinstance(objectslist, list):
        objectslist = [objectslist]
    newobjlist = []
    for obj in objectslist:
        if copy:
            newobj = make_copy.make_copy(obj)
        else:
            newobj = obj
        if hasattr(obj, 'Shape'):
            scaled_shape = obj.Shape.copy()
            m = App.Matrix()
            m.move(center.negative())
            m.scale(scale.x, scale.y, scale.z)
            m.move(center)
            scaled_shape = scaled_shape.transformGeometry(m)
        if utils.get_type(obj) == "Rectangle":
            p = []
            for v in scaled_shape.Vertexes:
                p.append(v.Point)
            pl = obj.Placement.copy()
            pl.Base = p[0]
            diag = p[2].sub(p[0])
            bb = p[1].sub(p[0])
            bh = p[3].sub(p[0])
            nb = DraftVecUtils.project(diag, bb)
            nh = DraftVecUtils.project(diag, bh)
            if obj.Length < 0: l = -nb.Length
            else: l = nb.Length
            if obj.Height < 0: h = -nh.Length
            else: h = nh.Length
            newobj.Length = l
            newobj.Height = h
            tr = p[0].sub(obj.Shape.Vertexes[0].Point)  # unused?
            newobj.Placement = pl
        elif utils.get_type(obj) == "Wire" or utils.get_type(obj) == "BSpline":
            for index, point in enumerate(newobj.Points):
                scale_vertex(newobj, index, scale, center)
        elif hasattr(obj, 'Shape'):
            newobj.Shape = scaled_shape
        elif (obj.TypeId == "App::Annotation"):
            factor = scale.y * obj.ViewObject.FontSize
            newobj.ViewObject.FontSize = factor
            d = obj.Position.sub(center)
            newobj.Position = center.add(
                App.Vector(d.x * scale.x, d.y * scale.y, d.z * scale.z))
        if copy:
            gui_utils.format_object(newobj, obj)
        newobjlist.append(newobj)
    if copy and utils.get_param("selectBaseObjects", False):
        gui_utils.select(objectslist)
    else:
        gui_utils.select(newobjlist)
    if len(newobjlist) == 1: return newobjlist[0]
    return newobjlist
Пример #3
0
def heal(objlist=None, delete=True, reparent=True):
    """heal([objlist],[delete],[reparent])
    
    Recreate Draft objects that are damaged, for example if created from an
    earlier version. If ran without arguments, all the objects in the document 
    will be healed if they are damaged.

    Parameters
    ----------
    objlist : list

    delete : Base.Vector or list of Base.Vector
        If delete is True, the damaged objects are deleted (default).

    reparent : bool
        If reparent is True (default), new objects go at the very same place 
        in the tree than their original.
    """

    auto = False

    if not objlist:
        objlist = App.ActiveDocument.Objects
        print("Automatic mode: Healing whole document...")
        auto = True
    else:
        print("Manual mode: Force-healing selected objects...")

    if not isinstance(objlist, list):
        objlist = [objlist]

    dellist = []
    got = False

    for obj in objlist:
        dtype = utils.get_type(obj)
        ftype = obj.TypeId
        if ftype in [
                "Part::FeaturePython", "App::FeaturePython",
                "Part::Part2DObjectPython", "Drawing::FeatureViewPython"
        ]:
            proxy = obj.Proxy
            if hasattr(obj, "ViewObject"):
                if hasattr(obj.ViewObject, "Proxy"):
                    proxy = obj.ViewObject.Proxy
            if (proxy == 1) or (dtype in ["Unknown", "Part"]) or (not auto):
                got = True
                dellist.append(obj.Name)
                props = obj.PropertiesList
                if ("Dimline" in props) and ("Start" in props):
                    print("Healing " + obj.Name + " of type Dimension")
                    nobj = make_copy(obj, force="Dimension", reparent=reparent)
                elif ("Height" in props) and ("Length" in props):
                    print("Healing " + obj.Name + " of type Rectangle")
                    nobj = make_copy(obj, force="Rectangle", reparent=reparent)
                elif ("Points" in props) and ("Closed" in props):
                    if "BSpline" in obj.Name:
                        print("Healing " + obj.Name + " of type BSpline")
                        nobj = make_copy(obj,
                                         force="BSpline",
                                         reparent=reparent)
                    else:
                        print("Healing " + obj.Name + " of type Wire")
                        nobj = make_copy(obj, force="Wire", reparent=reparent)
                elif ("Radius" in props) and ("FirstAngle" in props):
                    print("Healing " + obj.Name + " of type Circle")
                    nobj = make_copy(obj, force="Circle", reparent=reparent)
                elif ("DrawMode" in props) and ("FacesNumber" in props):
                    print("Healing " + obj.Name + " of type Polygon")
                    nobj = make_copy(obj, force="Polygon", reparent=reparent)
                elif ("FillStyle" in props) and ("FontSize" in props):
                    nobj = make_copy(obj,
                                     force="DrawingView",
                                     reparent=reparent)
                else:
                    dellist.pop()
                    print("Object " + obj.Name + " is not healable")

    if not got:
        print("No object seems to need healing")
    else:
        print("Healed ", len(dellist), " objects")

    if dellist and delete:
        for n in dellist:
            App.ActiveDocument.removeObject(n)
Пример #4
0
def move(objectslist, vector, copy=False):
    """move(objects,vector,[copy])
    
    Move the objects contained in objects (that can be an object or a
    list of objects) in the direction and distance indicated by the given
    vector. 

    Parameters
    ----------
    objectslist : list

    vector : Base.Vector
        Delta Vector to move the clone from the original position. 

    copy : bool
        If copy is True, the actual objects are not moved, but copies
        are created instead. 

    Return
    ----------
    The objects (or their copies) are returned.
    """
    utils.type_check([(vector, App.Vector), (copy, bool)], "move")
    if not isinstance(objectslist, list): objectslist = [objectslist]
    objectslist.extend(utils.get_movable_children(objectslist))
    newobjlist = []
    newgroups = {}
    objectslist = utils.filter_objects_for_modifiers(objectslist, copy)

    for obj in objectslist:
        newobj = None
        # real_vector have been introduced to take into account
        # the possibility that object is inside an App::Part
        # TODO: Make Move work also with App::Link
        if hasattr(obj, "getGlobalPlacement"):
            v_minus_global = obj.getGlobalPlacement().inverse(
            ).Rotation.multVec(vector)
            real_vector = obj.Placement.Rotation.multVec(v_minus_global)
        else:
            real_vector = vector

        if utils.get_type(obj) == "Point":
            if copy:
                newobj = make_copy(obj)
            else:
                newobj = obj
            newobj.X = obj.X + real_vector.x
            newobj.Y = obj.Y + real_vector.y
            newobj.Z = obj.Z + real_vector.z

        elif obj.isDerivedFrom("App::DocumentObjectGroup"):
            pass

        elif hasattr(obj, 'Shape'):
            if copy:
                newobj = make_copy(obj)
            else:
                newobj = obj
            pla = newobj.Placement
            pla.move(real_vector)

        elif utils.get_type(obj) == "Annotation":
            if copy:
                newobj = make_copy(obj)
            else:
                newobj = obj
            newobj.Position = obj.Position.add(real_vector)

        elif utils.get_type(obj) == "Text":
            if copy:
                newobj = make_copy(obj)
            else:
                newobj = obj
            newobj.Placement.Base = obj.Placement.Base.add(real_vector)

        elif utils.get_type(obj) in ["Dimension", "LinearDimension"]:
            if copy:
                newobj = make_copy(obj)
            else:
                newobj = obj
            newobj.Start = obj.Start.add(real_vector)
            newobj.End = obj.End.add(real_vector)
            newobj.Dimline = obj.Dimline.add(real_vector)

        elif utils.get_type(obj) in ["AngularDimension"]:
            if copy:
                newobj = make_copy(obj)
            else:
                newobj = obj
            newobj.Center = obj.Start.add(real_vector)

        elif "Placement" in obj.PropertiesList:
            if copy:
                newobj = make_copy(obj)
            else:
                newobj = obj
            pla = obj.Placement
            pla.move(real_vector)

        if newobj is not None:
            newobjlist.append(newobj)

        if copy:
            for p in obj.InList:
                if p.isDerivedFrom("App::DocumentObjectGroup") and (
                        p in objectslist):
                    g = newgroups.setdefault(
                        p.Name, App.ActiveDocument.addObject(p.TypeId, p.Name))
                    g.addObject(newobj)
                    break
                if utils.get_type(p) == "Layer":
                    p.Proxy.addObject(p, newobj)

    if copy and utils.get_param("selectBaseObjects", False):
        gui_utils.select(objectslist)
    else:
        gui_utils.select(newobjlist)
    if len(newobjlist) == 1: return newobjlist[0]
    return newobjlist
Пример #5
0
def rotate(objectslist,
           angle,
           center=App.Vector(0, 0, 0),
           axis=App.Vector(0, 0, 1),
           copy=False):
    """rotate(objects,angle,[center,axis,copy])

    Rotates the objects contained in objects (that can be a list of objects
    or an object) of the given angle (in degrees) around the center, using
    axis as a rotation axis.

    Parameters
    ----------
    objectslist : list

    angle : rotation angle (in degrees)

    center : Base.Vector

    axis : Base.Vector
        If axis is omitted, the rotation will be around the vertical Z axis.

    copy : bool
        If copy is True, the actual objects are not moved, but copies
        are created instead.

    Return
    ----------
    The objects (or their copies) are returned.
    """
    import Part
    utils.type_check([(copy, bool)], "rotate")
    if not isinstance(objectslist, list):
        objectslist = [objectslist]

    objectslist.extend(groups.get_movable_children(objectslist))
    newobjlist = []
    newgroups = {}
    objectslist = utils.filter_objects_for_modifiers(objectslist, copy)

    if copy:
        doc = App.ActiveDocument
        for obj in objectslist:
            if obj.isDerivedFrom("App::DocumentObjectGroup") \
                    and obj.Name not in newgroups.keys():
                newgroups[obj.Name] = doc.addObject(
                    obj.TypeId, utils.get_real_name(obj.Name))

    for obj in objectslist:
        newobj = None

        # real_center and real_axis are introduced to take into account
        # the possibility that object is inside an App::Part
        if hasattr(obj, "getGlobalPlacement"):
            ci = obj.getGlobalPlacement().inverse().multVec(center)
            real_center = obj.Placement.multVec(ci)
            ai = obj.getGlobalPlacement().inverse().Rotation.multVec(axis)
            real_axis = obj.Placement.Rotation.multVec(ai)
        else:
            real_center = center
            real_axis = axis

        if obj.isDerivedFrom("App::Annotation"):
            # TODO: this is very different from how move handle annotations
            # maybe we can uniform the two methods
            if copy:
                newobj = make_copy.make_copy(obj)
            else:
                newobj = obj
            if axis.normalize() == App.Vector(1, 0, 0):
                newobj.ViewObject.RotationAxis = "X"
                newobj.ViewObject.Rotation = angle
            elif axis.normalize() == App.Vector(0, 1, 0):
                newobj.ViewObject.RotationAxis = "Y"
                newobj.ViewObject.Rotation = angle
            elif axis.normalize() == App.Vector(0, -1, 0):
                newobj.ViewObject.RotationAxis = "Y"
                newobj.ViewObject.Rotation = -angle
            elif axis.normalize() == App.Vector(0, 0, 1):
                newobj.ViewObject.RotationAxis = "Z"
                newobj.ViewObject.Rotation = angle
            elif axis.normalize() == App.Vector(0, 0, -1):
                newobj.ViewObject.RotationAxis = "Z"
                newobj.ViewObject.Rotation = -angle

        elif utils.get_type(obj) == "Point":
            if copy:
                newobj = make_copy.make_copy(obj)
            else:
                newobj = obj
            v = App.Vector(newobj.X, newobj.Y, newobj.Z)
            rv = v.sub(real_center)
            rv = DraftVecUtils.rotate(rv, math.radians(angle), real_axis)
            v = real_center.add(rv)
            newobj.X = v.x
            newobj.Y = v.y
            newobj.Z = v.z

        elif obj.isDerivedFrom("App::DocumentObjectGroup"):
            if copy:
                newobj = newgroups[obj.Name]
            else:
                newobj = obj

        elif hasattr(obj, "Placement"):
            # App.Console.PrintMessage("placement rotation\n")
            if copy:
                newobj = make_copy.make_copy(obj)
            else:
                newobj = obj
            # Workaround for `faulty` implementation of Base.Placement.rotate(center, axis, angle).
            # See: https://forum.freecadweb.org/viewtopic.php?p=613196#p613196
            offset_rotation = App.Placement(App.Vector(0, 0, 0),
                                            App.Rotation(real_axis, angle),
                                            real_center)
            newobj.Placement = offset_rotation * newobj.Placement

        elif hasattr(obj, "Shape"):
            if copy:
                newobj = make_copy.make_copy(obj)
            else:
                newobj = obj
            shape = newobj.Shape.copy()
            shape.rotate(real_center, real_axis, angle)
            newobj.Shape = shape

        if newobj is not None:
            newobjlist.append(newobj)
            if copy:
                for parent in obj.InList:
                    if parent.isDerivedFrom("App::DocumentObjectGroup") \
                            and (parent in objectslist):
                        newgroups[parent.Name].addObject(newobj)
                    if utils.get_type(parent) == "Layer":
                        parent.Proxy.addObject(parent, newobj)

    if copy and utils.get_param("selectBaseObjects", False):
        gui_utils.select(objectslist)
    else:
        gui_utils.select(newobjlist)

    if len(newobjlist) == 1:
        return newobjlist[0]
    return newobjlist