# *************************************************************************** # * Copyright (c) 2009, 2010 Yorik van Havre * # * Copyright (c) 2009, 2010 Ken Cline * # * Copyright (c) 2020 FreeCAD Developers * # * * # * This program is free software; you can redistribute it and/or modify * # * it under the terms of the GNU Lesser General Public License (LGPL) * # * as published by the Free Software Foundation; either version 2 of * # * the License, or (at your option) any later version. * # * for detail see the LICENCE text file. * # * * # * This program is distributed in the hope that it will be useful, * # * but WITHOUT ANY WARRANTY; without even the implied warranty of * # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * # * GNU Library General Public License for more details. * # * * # * You should have received a copy of the GNU Library General Public * # * License along with this program; if not, write to the Free Software * # * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * # * USA * # * * # *************************************************************************** """Provides functions to scale shapes.""" ## @package scale # \ingroup draftfunctions # \brief Provides functions to scale shapes. ## \addtogroup draftfunctions # @{ import FreeCAD as App import DraftVecUtils from draftfunctions import join from draftmake import make_copy from draftmake import make_line from draftutils import gui_utils from draftutils import params from draftutils import utils 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 hasattr(obj,"Position"): d = obj.Position.sub(center) newobj.Position = center.add(App.Vector(d.x * scale.x, d.y * scale.y, d.z * scale.z)) elif hasattr(obj,"Placement"): d = obj.Placement.Base.sub(center) newobj.Placement.Base = center.add(App.Vector(d.x * scale.x, d.y * scale.y, d.z * scale.z)) if hasattr(obj,"Height"): obj.setExpression('Height', None) obj.Height = obj.Height * scale.y if hasattr(obj,"Width"): obj.setExpression('Width', None) obj.Width = obj.Width * scale.x if hasattr(obj,"XSize"): obj.setExpression('XSize', None) obj.XSize = obj.XSize * scale.x if hasattr(obj,"YSize"): obj.setExpression('YSize', None) obj.YSize = obj.YSize * scale.y if obj.ViewObject and hasattr(obj.ViewObject,"FontSize"): obj.ViewObject.FontSize = obj.ViewObject.FontSize * scale.y if copy: gui_utils.format_object(newobj,obj) newobjlist.append(newobj) if copy and params.get_param("selectBaseObjects"): gui_utils.select(objectslist) else: gui_utils.select(newobjlist) if len(newobjlist) == 1: return newobjlist[0] return newobjlist # Following functions are needed for SubObjects modifiers # implemented by Dion Moult during 0.19 dev cycle (works only with Draft Wire) def scale_vertex(obj, vertex_index, scale, center): """ Needed for SubObjects modifiers. Implemented by Dion Moult during 0.19 dev cycle (works only with Draft Wire). """ points = obj.Points points[vertex_index] = obj.getGlobalPlacement().inverse().multVec( scale_vector_from_center( obj.getGlobalPlacement().multVec(points[vertex_index]), scale, center)) obj.Points = points scaleVertex = scale_vertex def scale_vector_from_center(vector, scale, center): """ Needed for SubObjects modifiers. Implemented by Dion Moult during 0.19 dev cycle (works only with Draft Wire). """ return vector.sub(center).scale(scale.x, scale.y, scale.z).add(center) scaleVectorFromCenter = scale_vector_from_center def scale_edge(obj, edge_index, scale, center): """ Needed for SubObjects modifiers. Implemented by Dion Moult during 0.19 dev cycle (works only with Draft Wire). """ scale_vertex(obj, edge_index, scale, center) if utils.is_closed_edge(edge_index, obj): scale_vertex(obj, 0, scale, center) else: scale_vertex(obj, edge_index+1, scale, center) scaleEdge = scale_edge def copy_scaled_edge(obj, edge_index, scale, center): """ Needed for SubObjects modifiers. Implemented by Dion Moult during 0.19 dev cycle (works only with Draft Wire). """ vertex1 = scale_vector_from_center( obj.getGlobalPlacement().multVec(obj.Points[edge_index]), scale, center) if utils.is_closed_edge(edge_index, obj): vertex2 = scale_vector_from_center( obj.getGlobalPlacement().multVec(obj.Points[0]), scale, center) else: vertex2 = scale_vector_from_center( obj.getGlobalPlacement().multVec(obj.Points[edge_index+1]), scale, center) return make_line.make_line(vertex1, vertex2) copyScaledEdge = copy_scaled_edge def copy_scaled_edges(arguments): """ Needed for SubObjects modifiers. Implemented by Dion Moult during 0.19 dev cycle (works only with Draft Wire). """ copied_edges = [] for argument in arguments: copied_edges.append(copy_scaled_edge(argument[0], argument[1], argument[2], argument[3])) join.join_wires(copied_edges) copyScaledEdges = copy_scaled_edges ## @}