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