Download src/Mod/Draft/drafttests/test_modification.py from AbdulElahGwaith/FreeCAD: direct link, hf CLI and curl.
- Browser
- Download file 30.5 kB
-
https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/Draft/drafttests/test_modification.py
- Command line
-
hf download hf://AbdulElahGwaith/FreeCAD/src/Mod/Draft/drafttests/test_modification.py
-
curl -L -o test_modification.py https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/Draft/drafttests/test_modification.py
30.5 kB
| # SPDX-License-Identifier: LGPL-2.1-or-later | |
| # *************************************************************************** | |
| # * Copyright (c) 2013 Yorik van Havre <yorik@uncreated.net> * | |
| # * Copyright (c) 2019 Eliud Cabrera Castillo <e.cabrera-castillo@tum.de> * | |
| # * Copyright (c) 2025 FreeCAD Project Association * | |
| # * * | |
| # * This file is part of the FreeCAD CAx development system. * | |
| # * * | |
| # * 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. * | |
| # * * | |
| # * FreeCAD 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 FreeCAD; if not, write to the Free Software * | |
| # * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * | |
| # * USA * | |
| # * * | |
| # *************************************************************************** | |
| """Unit tests for the Draft Workbench, object modification tests.""" | |
| ## @package test_modification | |
| # \ingroup drafttests | |
| # \brief Unit tests for the Draft Workbench, object modification tests. | |
| ## \addtogroup drafttests | |
| # @{ | |
| import FreeCAD as App | |
| import Part | |
| import Draft | |
| from FreeCAD import Vector | |
| from drafttests import auxiliary as aux | |
| from drafttests import test_base | |
| from draftutils.messages import _msg | |
| class DraftModification(test_base.DraftTestCaseDoc): | |
| """Test Draft modification tools.""" | |
| def test_move(self): | |
| """Create a line and move it.""" | |
| operation = "Draft Move" | |
| _msg(" Test '{}'".format(operation)) | |
| a = Vector(0, 2, 0) | |
| b = Vector(2, 2, 0) | |
| _msg(" Line") | |
| _msg(" a={0}, b={1}".format(a, b)) | |
| obj = Draft.make_line(a, b) | |
| self.doc.recompute() | |
| c = Vector(3, 1, 0) | |
| _msg(" Translation vector") | |
| _msg(" c={}".format(c)) | |
| Draft.move(obj, c) | |
| self.doc.recompute() | |
| self.assertTrue(obj.Start.isEqual(Vector(3, 3, 0), 1e-6), "'{}' failed".format(operation)) | |
| def test_copy(self): | |
| """Create a line, then copy and move it.""" | |
| operation = "Draft Move with copy" | |
| _msg(" Test '{}'".format(operation)) | |
| a = Vector(0, 3, 0) | |
| b = Vector(2, 3, 0) | |
| _msg(" Line") | |
| _msg(" a={0}, b={1}".format(a, b)) | |
| line = Draft.make_line(a, b) | |
| c = Vector(2, 2, 0) | |
| _msg(" Translation vector (copy)") | |
| _msg(" c={}".format(c)) | |
| obj = Draft.move(line, c, copy=True) | |
| self.assertTrue(obj, "'{}' failed".format(operation)) | |
| def test_rotate(self): | |
| """Create a line, then rotate it.""" | |
| operation = "Draft Rotate" | |
| _msg(" Test '{}'".format(operation)) | |
| a = Vector(1, 1, 0) | |
| b = Vector(3, 1, 0) | |
| _msg(" Line") | |
| _msg(" a={0}, b={1}".format(a, b)) | |
| obj = Draft.make_line(a, b) | |
| self.doc.recompute() | |
| c = Vector(-1, 1, 0) | |
| rot = 90 | |
| _msg(" Rotation") | |
| _msg(" angle={} degrees".format(rot)) | |
| Draft.rotate(obj, rot) | |
| self.doc.recompute() | |
| self.assertTrue(obj.Start.isEqual(c, 1e-6), "'{}' failed".format(operation)) | |
| def test_offset_open(self): | |
| """Create an open wire, then produce an offset copy.""" | |
| operation = "Draft Offset" | |
| _msg(" Test '{}'".format(operation)) | |
| a = Vector(0, 2, 0) | |
| b = Vector(2, 4, 0) | |
| c = Vector(5, 2, 0) | |
| _msg(" Open wire") | |
| _msg(" a={0}, b={1}".format(a, b)) | |
| _msg(" c={0}".format(c)) | |
| wire = Draft.make_wire([a, b, c]) | |
| self.doc.recompute() | |
| offset = Vector(-1, 1, 0) | |
| _msg(" Offset") | |
| _msg(" vector={}".format(offset)) | |
| obj = Draft.offset(wire, offset, copy=True) | |
| self.assertTrue(obj, "'{}' failed".format(operation)) | |
| def test_offset_closed_with_reversed_edge(self): | |
| """Create a closed wire with a reversed edge, then produce an offset copy.""" | |
| # Regression test for: | |
| # https://github.com/FreeCAD/FreeCAD/pull/5496 | |
| operation = "Draft Offset" | |
| _msg(" Test '{}'".format(operation)) | |
| _msg(" Closed wire with reversed edge") | |
| a = Vector(0, 0, 0) | |
| b = Vector(10, 0, 0) | |
| c = Vector(10, 4, 0) | |
| d = Vector(0, 4, 0) | |
| edges = [Part.makeLine(a, b), Part.makeLine(b, c), Part.makeLine(c, d), Part.makeLine(a, d)] | |
| wire = Part.Wire(edges) | |
| obj = self.doc.addObject("Part::Feature") | |
| obj.Shape = wire | |
| offset = Vector(0, -1, 0) | |
| new = Draft.offset(obj, offset, copy=True) | |
| self.assertTrue(len(new.Points) == 4, "'{}' failed".format(operation)) | |
| def test_offset_rectangle_with_face(self): | |
| """Create a rectangle with a face, then produce an offset copy.""" | |
| # Regression test for: | |
| # https://github.com/FreeCAD/FreeCAD/pull/7670 | |
| operation = "Draft Offset" | |
| _msg(" Test '{}'".format(operation)) | |
| length = 10 | |
| width = 4 | |
| _msg(" Rectangle with face") | |
| _msg(" length={0}, width={1}".format(length, width)) | |
| rect = Draft.make_rectangle(length, width) | |
| rect.MakeFace = True | |
| self.doc.recompute() | |
| offset = Vector(0, -1, 0) | |
| _msg(" Offset") | |
| _msg(" vector={}".format(offset)) | |
| obj = Draft.offset(rect, offset, copy=True) | |
| self.doc.recompute() | |
| obj_is_ok = ( | |
| obj.Shape.CenterOfGravity == Vector(5, 2, 0) and obj.Length == 12 and obj.Height == 6 | |
| ) | |
| self.assertTrue(obj_is_ok, "'{}' failed".format(operation)) | |
| def test_trim(self): | |
| """Trim a line. NOT IMPLEMENTED.""" | |
| operation = "Draft Trimex trim" | |
| _msg(" Test '{}'".format(operation)) | |
| a = Vector(0, 0, 0) | |
| b = Vector(3, 3, 0) | |
| _msg(" Line") | |
| _msg(" a={0}, b={1}".format(a, b)) | |
| line = Draft.make_line(a, b) | |
| c = Vector(2, 2, 0) | |
| d = Vector(4, 2, 0) | |
| _msg(" Line 2") | |
| _msg(" c={0}, d={1}".format(c, d)) | |
| line2 = Draft.make_line(c, d) | |
| self.doc.recompute() | |
| obj = aux.fake_function(line, line2) | |
| self.assertTrue(obj, "'{}' failed".format(operation)) | |
| def test_extend(self): | |
| """Extend a line. NOT IMPLEMENTED.""" | |
| operation = "Draft Trimex extend" | |
| _msg(" Test '{}'".format(operation)) | |
| a = Vector(0, 0, 0) | |
| b = Vector(1, 1, 0) | |
| _msg(" Line") | |
| _msg(" a={0}, b={1}".format(a, b)) | |
| line = Draft.make_line(a, b) | |
| c = Vector(2, 2, 0) | |
| d = Vector(4, 2, 0) | |
| _msg(" Line 2") | |
| _msg(" c={0}, d={1}".format(c, d)) | |
| line2 = Draft.make_line(c, d) | |
| self.doc.recompute() | |
| obj = aux.fake_function(line, line2) | |
| self.assertTrue(obj, "'{}' failed".format(operation)) | |
| def test_join(self): | |
| """Join two lines into a single Draft Wire.""" | |
| operation = "Draft Join" | |
| _msg(" Test '{}'".format(operation)) | |
| a = Vector(0, 0, 0) | |
| b = Vector(2, 2, 0) | |
| c = Vector(2, 4, 0) | |
| _msg(" Line 1") | |
| _msg(" a={0}, b={1}".format(a, b)) | |
| _msg(" Line 2") | |
| _msg(" b={0}, c={1}".format(b, c)) | |
| line_1 = Draft.make_line(a, b) | |
| line_2 = Draft.make_line(b, c) | |
| # obj = Draft.join_wires([line_1, line_2]) # Multiple wires | |
| obj = Draft.join_two_wires(line_1, line_2) | |
| self.assertTrue(obj, "'{}' failed".format(operation)) | |
| def test_split(self): | |
| """Split a Draft Wire into two Draft Wires.""" | |
| operation = "Draft_Split" | |
| _msg(" Test '{}'".format(operation)) | |
| a = Vector(0, 0, 0) | |
| b = Vector(2, 2, 0) | |
| c = Vector(2, 4, 0) | |
| d = Vector(6, 4, 0) | |
| _msg(" Wire") | |
| _msg(" a={0}, b={1}".format(a, b)) | |
| _msg(" c={0}, d={1}".format(c, d)) | |
| wire = Draft.make_wire([a, b, c, d]) | |
| self.doc.recompute() | |
| index = 1 | |
| _msg(" Split at") | |
| _msg(" p={0}, index={1}".format(b, index)) | |
| obj = Draft.split(wire, b, index) | |
| # TODO: split needs to be modified so that it returns True or False. | |
| # Then checking for Wire001 is not needed | |
| if self.doc.Wire001: | |
| obj = True | |
| self.assertTrue(obj, "'{}' failed".format(operation)) | |
| def test_upgrade(self): | |
| """Upgrade two Lines into a closed Wire, then draftify it.""" | |
| operation = "Draft Upgrade" | |
| _msg(" Test '{}'".format(operation)) | |
| a = Vector(0, 0, 0) | |
| b = Vector(2, 2, 0) | |
| c = Vector(2, 4, 0) | |
| _msg(" Line 1") | |
| _msg(" a={0}, b={1}".format(a, b)) | |
| _msg(" Line 2") | |
| _msg(" b={0}, c={1}".format(b, c)) | |
| shape_line_1 = Part.makeLine(a, b) | |
| shape_line_2 = Part.makeLine(b, c) | |
| line_1 = self.doc.addObject("Part::Feature") | |
| line_2 = self.doc.addObject("Part::Feature") | |
| line_1.Shape = shape_line_1 | |
| line_2.Shape = shape_line_2 | |
| self.doc.recompute() | |
| # upgrade to wire | |
| obj = Draft.upgrade([line_1, line_2], delete=True) | |
| self.doc.recompute() | |
| s = obj[0][0] | |
| _msg(" 1: Result '{0}' ({1})".format(s.Shape.ShapeType, s.TypeId)) | |
| self.assertTrue(bool(obj[0]), "'{}' failed".format(operation)) | |
| # upgrade to closed wire | |
| obj2 = Draft.upgrade(obj[0], delete=True) | |
| self.doc.recompute() | |
| s2 = obj2[0][0] | |
| _msg(" 2: Result '{0}' ({1})".format(s2.Shape.ShapeType, s2.TypeId)) | |
| self.assertTrue(bool(obj2[0]), "'{}' failed".format(operation)) | |
| # upgrade to face | |
| obj3 = Draft.upgrade(obj2[0], delete=True) | |
| self.doc.recompute() | |
| s3 = obj3[0][0] | |
| _msg(" 3: Result '{0}' ({1})".format(s3.Shape.ShapeType, s3.TypeId)) | |
| self.assertTrue(bool(obj3[0]), "'{}' failed".format(operation)) | |
| # upgrade to Draft_Wire | |
| Draft.upgrade(obj3[0], delete=True) | |
| # when draftifying, upgrade doesn't return a new object | |
| wire = self.doc.ActiveObject | |
| wire.MakeFace = True # make test independent of MakeFaceMode parameter | |
| self.doc.recompute() | |
| _msg(" 4: Result '{0}' ({1})".format(wire.Proxy.Type, wire.TypeId)) | |
| self.assertTrue(bool(wire), "'{}' failed".format(operation)) | |
| # Draft_Wire with face cannot be upgraded | |
| obj4 = Draft.upgrade(wire, delete=True) | |
| self.doc.recompute() | |
| _msg(" The last object cannot be upgraded further") | |
| self.assertFalse(bool(obj4[0]), "'{}' failed".format(operation)) | |
| def test_downgrade(self): | |
| """Downgrade a closed Draft Wire into three simple Part Edges.""" | |
| operation = "Draft Downgrade" | |
| _msg(" Test '{}'".format(operation)) | |
| a = Vector(0, 0, 0) | |
| b = Vector(2, 2, 0) | |
| c = Vector(2, 4, 0) | |
| _msg(" Closed wire") | |
| _msg(" a={0}, b={1}".format(a, b)) | |
| _msg(" c={0}, a={1}".format(c, a)) | |
| wire = Draft.make_wire([a, b, c, a]) | |
| wire.MakeFace = True # make test independent of MakeFaceMode parameter | |
| self.doc.recompute() | |
| # downgrade to face | |
| obj = Draft.downgrade(wire, delete=True) | |
| self.doc.recompute() | |
| s = obj[0][0] | |
| _msg(" 1: Result '{0}' ({1})".format(s.Shape.ShapeType, s.TypeId)) | |
| self.assertTrue(bool(obj[0]), "'{}' failed".format(operation)) | |
| # downgrade to wire | |
| obj2 = Draft.downgrade(obj[0], delete=True) | |
| self.doc.recompute() | |
| s2 = obj2[0][0] | |
| _msg(" 2: Result '{0}' ({1})".format(s2.Shape.ShapeType, s2.TypeId)) | |
| self.assertTrue(bool(obj2[0]), "'{}' failed".format(operation)) | |
| # downgrade to edges | |
| obj3 = Draft.downgrade(obj2[0], delete=True) | |
| self.doc.recompute() | |
| s3 = obj3[0][0] | |
| _msg(" 3: Result 3 x '{0}' ({1})".format(s3.Shape.ShapeType, s3.TypeId)) | |
| self.assertTrue(len(obj3[0]) == 3, "'{}' failed".format(operation)) | |
| # edges cannot be downgraded | |
| obj4 = Draft.downgrade(obj3[0], delete=True) | |
| self.doc.recompute() | |
| s4 = obj4[0] | |
| _msg(" 4: Result '{}'".format(s4)) | |
| _msg(" The last objects cannot be downgraded further") | |
| self.assertFalse(bool(obj4[0]), "'{}' failed".format(operation)) | |
| def test_wire_to_bspline(self): | |
| """Convert a polyline to BSpline and back.""" | |
| operation = "Draft WireToBSpline" | |
| _msg(" Test '{}'".format(operation)) | |
| a = Vector(0, 0, 0) | |
| b = Vector(2, 2, 0) | |
| c = Vector(2, 4, 0) | |
| _msg(" Wire") | |
| _msg(" a={0}, b={1}".format(a, b)) | |
| _msg(" c={}".format(c)) | |
| wire = Draft.make_wire([a, b, c]) | |
| obj = Draft.make_bspline(wire.Points) | |
| self.doc.recompute() | |
| _msg(" 1: Result '{0}' ({1})".format(obj.Proxy.Type, obj.TypeId)) | |
| self.assertTrue(obj, "'{}' failed".format(operation)) | |
| obj2 = Draft.make_wire(obj.Points) | |
| _msg(" 2: Result '{0}' ({1})".format(obj2.Proxy.Type, obj2.TypeId)) | |
| self.assertTrue(obj2, "'{}' failed".format(operation)) | |
| def test_shape_2d_view(self): | |
| """Create a prism and then a 2D projection of it.""" | |
| operation = "Draft Shape2DView" | |
| _msg(" Test '{}'".format(operation)) | |
| prism = self.doc.addObject("Part::Prism") | |
| prism.Polygon = 5 | |
| # Rotate the prism 45 degrees around the Y axis | |
| prism.Placement.Rotation.Axis = Vector(0, 1, 0) | |
| prism.Placement.Rotation.Angle = 45 * (3.14159 / 180) | |
| _msg(" Prism") | |
| _msg(" n_sides={}".format(prism.Polygon)) | |
| _msg(" placement={}".format(prism.Placement)) | |
| direction = Vector(0, 0, 1) | |
| _msg(" Projection 2D view") | |
| _msg(" direction={}".format(direction)) | |
| obj = Draft.make_shape2dview(prism, direction) | |
| self.assertTrue(obj, "'{}' failed".format(operation)) | |
| def test_draft_to_sketch(self): | |
| """Convert a Draft object to a Sketch and back.""" | |
| operation = "Draft Draft2Sketch" | |
| _msg(" Test '{}'".format(operation)) | |
| a = Vector(0, 0, 0) | |
| b = Vector(2, 2, 0) | |
| c = Vector(2, 4, 0) | |
| _msg(" Wire") | |
| _msg(" a={0}, b={1}".format(a, b)) | |
| _msg(" c={}".format(c)) | |
| wire = Draft.make_wire([a, b, c]) | |
| self.doc.recompute() | |
| obj = Draft.make_sketch(wire, autoconstraints=True) | |
| self.doc.recompute() | |
| _msg(" 1: Result '{0}' ({1})".format(obj.Shape.ShapeType, obj.TypeId)) | |
| self.assertTrue(obj, "'{}' failed".format(operation)) | |
| obj2 = Draft.draftify(obj, delete=False) | |
| self.doc.recompute() | |
| _msg(" 2: Result '{0}' ({1})".format(obj2.Proxy.Type, obj2.TypeId)) | |
| self.assertTrue(obj2, "'{}' failed".format(operation)) | |
| def test_rectangular_array(self): | |
| """Create a rectangle, and a rectangular array.""" | |
| operation = "Draft OrthoArray" | |
| _msg(" Test '{}'".format(operation)) | |
| length = 4 | |
| width = 2 | |
| _msg(" Rectangle") | |
| _msg(" length={0}, width={1}".format(length, width)) | |
| rect = Draft.make_rectangle(length, width) | |
| self.doc.recompute() | |
| dir_x = Vector(5, 0, 0) | |
| dir_y = Vector(0, 4, 0) | |
| dir_z = Vector(0, 0, 6) | |
| number_x = 3 | |
| number_y = 4 | |
| number_z = 6 | |
| _msg(" Array") | |
| _msg(" direction_x={}".format(dir_x)) | |
| _msg(" direction_y={}".format(dir_y)) | |
| _msg(" direction_z={}".format(dir_z)) | |
| _msg(" number_x={0}, number_y={1}, number_z={2}".format(number_x, number_y, number_z)) | |
| obj = Draft.make_ortho_array(rect, dir_x, dir_y, dir_z, number_x, number_y, number_z) | |
| self.assertTrue(obj, "'{}' failed".format(operation)) | |
| def test_polar_array(self): | |
| """Create a rectangle, and a polar array.""" | |
| operation = "Draft PolarArray" | |
| _msg(" Test '{}'".format(operation)) | |
| length = 4 | |
| width = 2 | |
| _msg(" Rectangle") | |
| _msg(" length={0}, width={1}".format(length, width)) | |
| rect = Draft.make_rectangle(length, width) | |
| self.doc.recompute() | |
| center = Vector(-4, 0, 0) | |
| angle = 180 | |
| number = 5 | |
| _msg(" Array") | |
| _msg(" number={0}, polar_angle={1}".format(number, angle)) | |
| _msg(" center={}".format(center)) | |
| obj = Draft.make_polar_array(rect, number, angle, center) | |
| self.assertTrue(obj, "'{}' failed".format(operation)) | |
| def test_circular_array(self): | |
| """Create a rectangle, and a circular array.""" | |
| operation = "Draft CircularArray" | |
| _msg(" Test '{}'".format(operation)) | |
| length = 4 | |
| width = 2 | |
| _msg(" Rectangle") | |
| _msg(" length={0}, width={1}".format(length, width)) | |
| rect = Draft.make_rectangle(length, width) | |
| self.doc.recompute() | |
| rad_distance = 10 | |
| tan_distance = 8 | |
| axis = Vector(0, 0, 1) | |
| center = Vector(0, 0, 0) | |
| number = 3 | |
| symmetry = 1 | |
| _msg(" Array") | |
| _msg(" radial_distance={0}, " "tangential_distance={1}".format(rad_distance, tan_distance)) | |
| _msg(" number={0}, symmetry={1}".format(number, symmetry)) | |
| _msg(" axis={}".format(axis)) | |
| _msg(" center={}".format(center)) | |
| obj = Draft.make_circular_array( | |
| rect, rad_distance, tan_distance, number, symmetry, axis, center | |
| ) | |
| self.assertTrue(obj, "'{}' failed".format(operation)) | |
| def test_path_array(self): | |
| """Create a wire, a polygon, and a path array.""" | |
| operation = "Draft PathArray" | |
| _msg(" Test '{}'".format(operation)) | |
| a = Vector(0, 0, 0) | |
| b = Vector(2, 2, 0) | |
| c = Vector(2, 4, 0) | |
| d = Vector(8, 4, 0) | |
| _msg(" Wire") | |
| _msg(" a={0}, b={1}".format(a, b)) | |
| _msg(" c={0}, d={1}".format(c, d)) | |
| wire = Draft.make_wire([a, b, c, d]) | |
| n_faces = 3 | |
| radius = 1 | |
| _msg(" Polygon") | |
| _msg(" n_faces={0}, radius={1}".format(n_faces, radius)) | |
| poly = Draft.make_polygon(n_faces, radius) | |
| number = 4 | |
| translation = Vector(0, 1, 0) | |
| subelements = "Edge1" | |
| align = False | |
| _msg(" Path Array") | |
| _msg(" number={}, translation={}".format(number, translation)) | |
| _msg(" subelements={}, align={}".format(subelements, align)) | |
| obj = Draft.make_path_array(poly, wire, number, translation, subelements, align) | |
| self.assertTrue(obj, "'{}' failed".format(operation)) | |
| def test_point_array(self): | |
| """Create a polygon, various point, and a point array.""" | |
| operation = "Draft PointArray" | |
| _msg(" Test '{}'".format(operation)) | |
| a = Vector(0, 0, 0) | |
| b = Vector(2, 2, 0) | |
| c = Vector(2, 4, 0) | |
| d = Vector(8, 4, 0) | |
| _msg(" Points") | |
| _msg(" a={0}, b={1}".format(a, b)) | |
| _msg(" c={0}, d={1}".format(c, d)) | |
| points = [ | |
| Draft.make_point(a), | |
| Draft.make_point(b), | |
| Draft.make_point(c), | |
| Draft.make_point(d), | |
| ] | |
| _msg(" Upgrade") | |
| add, delete = Draft.upgrade(points) | |
| compound = add[0] | |
| n_faces = 3 | |
| radius = 1 | |
| _msg(" Polygon") | |
| _msg(" n_faces={0}, radius={1}".format(n_faces, radius)) | |
| poly = Draft.make_polygon(n_faces, radius) | |
| _msg(" Point Array") | |
| obj = Draft.make_point_array(poly, compound) | |
| self.assertTrue(obj, "'{}' failed".format(operation)) | |
| def test_clone(self): | |
| """Create a box, then create a clone of it. | |
| Test for a bug introduced by changes in attachment code. | |
| """ | |
| operation = "Draft Clone" | |
| _msg(" Test '{}'".format(operation)) | |
| box = self.doc.addObject("Part::Box") | |
| self.doc.recompute() | |
| _msg(" object: '{0}' ({1})".format(box.Shape.ShapeType, box.TypeId)) | |
| obj = Draft.make_clone(box) | |
| _msg(" clone: '{0}' ({1})".format(obj.Proxy.Type, obj.TypeId)) | |
| self.assertTrue(obj, "'{}' failed".format(operation)) | |
| self.assertTrue(obj.hasExtension("Part::AttachExtension"), "'{}' failed".format(operation)) | |
| def test_attached_clone_behavior(self): | |
| """Check if an attached clone behaves correctly. | |
| Test for https://github.com/FreeCAD/FreeCAD/issues/8771. | |
| """ | |
| operation = "Check attached Draft Clone behavior" | |
| _msg(" Test '{}'".format(operation)) | |
| box1 = self.doc.addObject("Part::Box") | |
| box1.Length = 10 | |
| box2 = self.doc.addObject("Part::Box") | |
| self.doc.recompute() | |
| obj = Draft.make_clone(box1) | |
| obj.MapMode = "ObjectXY" | |
| obj.AttachmentSupport = [(box2, ("",))] | |
| self.doc.recompute() | |
| box1.Length = 1 | |
| self.doc.recompute() | |
| self.assertTrue(obj.Shape.BoundBox.XLength == 1, "'{}' failed".format(operation)) | |
| def test_draft_to_techdraw(self): | |
| """Create a solid, and then a DraftView on a TechDraw page.""" | |
| operation = "TechDraw DraftView (relies on Draft code)" | |
| _msg(" Test '{}'".format(operation)) | |
| prism = self.doc.addObject("Part::Prism") | |
| prism.Polygon = 5 | |
| # Rotate the prism 45 degrees around the Y axis | |
| prism.Placement.Rotation.Axis = Vector(0, 1, 0) | |
| prism.Placement.Rotation.Angle = 45 * (3.14159 / 180) | |
| _msg(" Prism") | |
| _msg(" n_sides={}".format(prism.Polygon)) | |
| _msg(" placement={}".format(prism.Placement)) | |
| page = self.doc.addObject("TechDraw::DrawPage") | |
| _msg(" page={}".format(page.TypeId)) | |
| template = self.doc.addObject("TechDraw::DrawSVGTemplate") | |
| template.Template = ( | |
| App.getResourceDir() + "Mod/TechDraw/Templates/ISO/A3_Landscape_blank.svg" | |
| ) | |
| page.Template = template | |
| _msg(" template={}".format(template.TypeId)) | |
| view = self.doc.addObject("TechDraw::DrawViewDraft") | |
| view.Source = prism | |
| view.Direction = App.Vector(0, 0, 1) | |
| page.addView(view) | |
| _msg(" view={}".format(view.TypeId)) | |
| self.assertTrue(view, "'{}' failed".format(operation)) | |
| self.assertTrue(view in page.OutList, "'{}' failed".format(operation)) | |
| def test_mirror(self): | |
| """Create a rectangle, then a mirrored shape.""" | |
| operation = "Draft Mirror" | |
| _msg(" Test '{}'".format(operation)) | |
| length = 4 | |
| width = 2 | |
| _msg(" Rectangle") | |
| _msg(" length={0}, width={1}".format(length, width)) | |
| rect = Draft.make_rectangle(length, width) | |
| # self.doc.recompute() | |
| p1 = Vector(6, -2, 0) | |
| p2 = Vector(6, 2, 0) | |
| _msg(" Mirror axis") | |
| _msg(" p1={}".format(p1)) | |
| _msg(" p2={}".format(p2)) | |
| obj = Draft.mirror(rect, p1, p2) | |
| self.assertTrue(obj, "'{}' failed".format(operation)) | |
| def test_stretch(self): | |
| """Stretch a line. NOT IMPLEMENTED.""" | |
| operation = "Draft Stretch" | |
| _msg(" Test '{}'".format(operation)) | |
| _msg(" This test requires an object and a selection") | |
| a = Vector(0, 0, 0) | |
| b = Vector(1, 1, 0) | |
| _msg(" Line") | |
| _msg(" a={0}, b={1}".format(a, b)) | |
| line = Draft.make_line(a, b) | |
| direction = Vector(4, 1, 0) | |
| obj = aux.fake_function(line, direction) | |
| self.assertTrue(obj, "'{}' failed".format(operation)) | |
| def test_scale_part_feature_arcs(self): | |
| """Create and scale a part feature (arcs).""" | |
| operation = "Draft Scale part feature (arcs)" | |
| _msg(" Test '{}'".format(operation)) | |
| base = Vector(3.5, 2.5, 0.0) | |
| cen = Vector(2.0, 1.0, 0.0) # center for scaling | |
| sca = Vector(2.0, 3.0, 1.0) | |
| ends = [ | |
| Vector(0.0, 0.0, 0.0), | |
| Vector(4.0, 0.0, 0.0), | |
| Vector(4.0, 3.0, 0.0), | |
| Vector(0.0, 3.0, 0.0), | |
| ] | |
| mids = [ | |
| Vector(2.0, -0.5, 0.0), | |
| Vector(4.5, 1.5, 0.0), | |
| Vector(2.0, 3.5, 0.0), | |
| Vector(-0.5, 1.5, 0.0), | |
| ] # arc midpoints | |
| shp = Part.Shape( | |
| [ | |
| Part.Arc(ends[0], mids[0], ends[1]), | |
| Part.Arc(ends[1], mids[1], ends[2]), | |
| Part.Arc(ends[2], mids[2], ends[3]), | |
| Part.Arc(ends[3], mids[3], ends[0]), | |
| ] | |
| ) | |
| obj = self.doc.addObject("Part::Feature") | |
| obj.Shape = shp | |
| obj.Placement.Base = base | |
| self.doc.recompute() | |
| obj = Draft.scale(obj, sca, cen, False) | |
| self.doc.recompute() | |
| # check endpoints of arcs: | |
| newEnds = [ | |
| Vector(5.0, 5.5, 0.0), | |
| Vector(13.0, 5.5, 0.0), | |
| Vector(13.0, 14.5, 0.0), | |
| Vector(5.0, 14.5, 0.0), | |
| ] | |
| vrts = obj.Shape.Vertexes | |
| for i in range(4): | |
| self.assertTrue( | |
| vrts[i].Point.isEqual(newEnds[i], 1e-6), "'{}' failed".format(operation) | |
| ) | |
| # check midpoints of arcs: | |
| newMids = [ | |
| Vector(9.0, 4.0, 0.0), | |
| Vector(14.0, 10.0, 0.0), | |
| Vector(9.0, 16.0, 0.0), | |
| Vector(4.0, 10.0, 0.0), | |
| ] | |
| for i in range(4): | |
| edge = obj.Shape.Edges[i] | |
| par = (edge.LastParameter - edge.FirstParameter) / 2.0 | |
| self.assertTrue( | |
| edge.valueAt(par).isEqual(newMids[i], 1e-6), "'{}' failed".format(operation) | |
| ) | |
| def test_scale_part_feature_lines(self): | |
| """Create and scale a part feature (lines).""" | |
| operation = "Draft Scale part feature (lines)" | |
| _msg(" Test '{}'".format(operation)) | |
| base = Vector(3.5, 2.5, 0.0) | |
| cen = Vector(2.0, 1.0, 0.0) # center for scaling | |
| sca = Vector(2.0, 3.0, 1.0) | |
| pts = [ | |
| Vector(0.0, 0.0, 0.0), | |
| Vector(4.0, 0.0, 0.0), | |
| Vector(4.0, 3.0, 0.0), | |
| Vector(0.0, 3.0, 0.0), | |
| ] | |
| shp = Part.Shape( | |
| [ | |
| Part.LineSegment(pts[0], pts[1]), | |
| Part.LineSegment(pts[1], pts[2]), | |
| Part.LineSegment(pts[2], pts[3]), | |
| Part.LineSegment(pts[3], pts[0]), | |
| ] | |
| ) | |
| obj = self.doc.addObject("Part::Feature") | |
| obj.Shape = shp | |
| obj.Placement.Base = base | |
| self.doc.recompute() | |
| obj = Draft.scale(obj, sca, cen, False) | |
| self.doc.recompute() | |
| newPts = [ | |
| Vector(5.0, 5.5, 0.0), | |
| Vector(13.0, 5.5, 0.0), | |
| Vector(13.0, 14.5, 0.0), | |
| Vector(5.0, 14.5, 0.0), | |
| ] | |
| vrts = obj.Shape.Vertexes | |
| for i in range(4): | |
| self.assertTrue(vrts[i].Point.isEqual(newPts[i], 1e-6), "'{}' failed".format(operation)) | |
| def test_scale_rectangle(self): | |
| """Create and scale a rectangle.""" | |
| operation = "Draft Scale rectangle" | |
| _msg(" Test '{}'".format(operation)) | |
| base = Vector(3.5, 2.5, 0.0) | |
| cen = Vector(2.0, 1.0, 0.0) # center for scaling | |
| sca = Vector(2.0, 3.0, 1.0) | |
| len = 4.0 | |
| hgt = 3.0 | |
| obj = Draft.make_rectangle(len, hgt) | |
| obj.Placement.Base = base | |
| self.doc.recompute() | |
| obj = Draft.scale(obj, sca, cen, False) | |
| self.doc.recompute() | |
| newBase = Vector(5.0, 5.5, 0.0) | |
| newLen = 8.0 | |
| newHgt = 9.0 | |
| self.assertTrue(obj.Placement.Base.isEqual(newBase, 1e-6), "'{}' failed".format(operation)) | |
| self.assertAlmostEqual(obj.Length, newLen, delta=1e-6, msg="'{}' failed".format(operation)) | |
| self.assertAlmostEqual(obj.Height, newHgt, delta=1e-6, msg="'{}' failed".format(operation)) | |
| def test_scale_spline(self): | |
| """Create and scale a spline.""" | |
| operation = "Draft Scale spline" | |
| _msg(" Test '{}'".format(operation)) | |
| base = Vector(3.5, 2.5, 0.0) | |
| cen = Vector(2.0, 1.0, 0.0) # center for scaling | |
| sca = Vector(2.0, 3.0, 1.0) | |
| pts = [Vector(0.0, 0.0, 0.0), Vector(2.0, 3.0, 0.0), Vector(4.0, 0.0, 0.0)] | |
| obj = Draft.make_bspline(pts, False) | |
| obj.Placement.Base = base | |
| self.doc.recompute() | |
| obj = Draft.scale(obj, sca, cen, False) | |
| self.doc.recompute() | |
| pla = obj.Placement | |
| newPts = [Vector(5.0, 5.5, 0.0), Vector(9.0, 14.5, 0.0), Vector(13.0, 5.5, 0.0)] | |
| for i in range(3): | |
| self.assertTrue( | |
| pla.multVec(obj.Points[i]).isEqual(newPts[i], 1e-6), "'{}' failed".format(operation) | |
| ) | |
| def test_scale_wire(self): | |
| """Create and scale a wire.""" | |
| operation = "Draft Scale wire" | |
| _msg(" Test '{}'".format(operation)) | |
| base = Vector(3.5, 2.5, 0.0) | |
| cen = Vector(2.0, 1.0, 0.0) # center for scaling | |
| sca = Vector(2.0, 3.0, 1.0) | |
| pts = [ | |
| Vector(0.0, 0.0, 0.0), | |
| Vector(4.0, 0.0, 0.0), | |
| Vector(4.0, 3.0, 0.0), | |
| Vector(0.0, 3.0, 0.0), | |
| ] | |
| obj = Draft.make_wire(pts, True) | |
| obj.Placement.Base = base | |
| self.doc.recompute() | |
| obj = Draft.scale(obj, sca, cen, False) | |
| self.doc.recompute() | |
| newPts = [ | |
| Vector(5.0, 5.5, 0.0), | |
| Vector(13.0, 5.5, 0.0), | |
| Vector(13.0, 14.5, 0.0), | |
| Vector(5.0, 14.5, 0.0), | |
| ] | |
| vrts = obj.Shape.Vertexes | |
| for i in range(4): | |
| self.assertTrue(vrts[i].Point.isEqual(newPts[i], 1e-6), "'{}' failed".format(operation)) | |
| ## @} | |