Download src/Mod/Draft/draftfunctions/offset.py from AbdulElahGwaith/FreeCAD: direct link, hf CLI and curl.
- Browser
- Download file 10.3 kB
-
https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/Draft/draftfunctions/offset.py
- Command line
-
hf download hf://AbdulElahGwaith/FreeCAD/src/Mod/Draft/draftfunctions/offset.py
-
curl -L -o offset.py https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/Draft/draftfunctions/offset.py
10.3 kB
| # SPDX-License-Identifier: LGPL-2.1-or-later | |
| # *************************************************************************** | |
| # * Copyright (c) 2009, 2010 Yorik van Havre <yorik@uncreated.net> * | |
| # * Copyright (c) 2009, 2010 Ken Cline <cline@frii.com> * | |
| # * 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 create offsets of different shapes.""" | |
| ## @package offset | |
| # \ingroup draftfunctions | |
| # \brief Provides functions to create offsets of different shapes. | |
| ## \addtogroup draftfunctions | |
| # @{ | |
| import math | |
| import FreeCAD as App | |
| import DraftVecUtils | |
| from draftutils import gui_utils | |
| from draftutils import params | |
| from draftutils import utils | |
| from draftmake.make_rectangle import make_rectangle | |
| from draftmake.make_wire import make_wire | |
| from draftmake.make_polygon import make_polygon | |
| from draftmake.make_circle import make_circle | |
| from draftmake.make_bspline import make_bspline | |
| def offset(obj, delta, copy=False, bind=False, sym=False, occ=False): | |
| """offset(object,delta,[copymode],[bind]) | |
| Offset the given wire by applying the given delta Vector to its first | |
| vertex. | |
| Parameters | |
| ---------- | |
| obj : | |
| delta : Base.Vector or list of Base.Vector | |
| If offsetting a BSpline, the delta must not be a Vector but a list | |
| of Vectors, one for each node of the spline. | |
| copy : bool | |
| If copymode is True, another object is created, otherwise the same | |
| object gets offsetted. | |
| copy : bool | |
| If bind is True, and provided the wire is open, the original | |
| and the offset wires will be bound by their endpoints, forming a face. | |
| sym : bool | |
| if sym is True, bind must be true too, and the offset is made on both | |
| sides, the total width being the given delta length. | |
| """ | |
| import Part | |
| import DraftGeomUtils | |
| newwire = None | |
| delete = None | |
| if copy is False and ( | |
| utils.get_type(obj).startswith("Sketcher::") | |
| or utils.get_type(obj).startswith("Part::") | |
| or utils.get_type(obj).startswith("PartDesign::") | |
| ): # For PartDesign_SubShapeBinders which can reference sketches. | |
| print( | |
| "the offset tool is currently unable to offset a non-Draft object directly - Creating a copy" | |
| ) | |
| copy = True | |
| def getRect(p, obj): | |
| """returns length,height,placement""" | |
| 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.Value < 0: | |
| l = -nb.Length | |
| else: | |
| l = nb.Length | |
| if obj.Height.Value < 0: | |
| h = -nh.Length | |
| else: | |
| h = nh.Length | |
| return l, h, pl | |
| def getRadius(obj, delta): | |
| """returns a new radius for a regular polygon""" | |
| an = math.pi / obj.FacesNumber | |
| nr = DraftVecUtils.rotate(delta, -an) | |
| nr.multiply(1 / math.cos(an)) | |
| nr = obj.Shape.Vertexes[0].Point.add(nr) | |
| nr = nr.sub(obj.Placement.Base) | |
| nr = nr.Length | |
| if obj.DrawMode == "inscribed": | |
| return nr | |
| else: | |
| return nr * math.cos(math.pi / obj.FacesNumber) | |
| newwire = None | |
| if utils.get_type(obj) == "Circle": | |
| pass | |
| elif utils.get_type(obj) == "BSpline": | |
| pass | |
| else: | |
| if sym: | |
| d1 = App.Vector(delta).multiply(0.5) | |
| d2 = d1.negative() | |
| n1 = DraftGeomUtils.offsetWire(obj.Shape, d1) | |
| n2 = DraftGeomUtils.offsetWire(obj.Shape, d2) | |
| else: | |
| if isinstance(delta, float) and (len(obj.Shape.Edges) == 1): | |
| # circle | |
| c = obj.Shape.Edges[0].Curve | |
| nc = Part.Circle(c.Center, c.Axis, delta) | |
| if len(obj.Shape.Vertexes) > 1: | |
| nc = Part.ArcOfCircle( | |
| nc, obj.Shape.Edges[0].FirstParameter, obj.Shape.Edges[0].LastParameter | |
| ) | |
| newwire = Part.Wire(nc.toShape()) | |
| p = [] | |
| else: | |
| newwire = DraftGeomUtils.offsetWire(obj.Shape, delta) | |
| if DraftGeomUtils.hasCurves(newwire) and copy: | |
| p = [] | |
| else: | |
| p = DraftGeomUtils.getVerts(newwire) | |
| if occ: | |
| newobj = App.ActiveDocument.addObject("Part::Feature", "Offset") | |
| newobj.Shape = DraftGeomUtils.offsetWire(obj.Shape, delta, occ=True) | |
| gui_utils.formatObject(newobj, obj) | |
| if not copy: | |
| delete = obj.Name | |
| elif bind: | |
| if not DraftGeomUtils.isReallyClosed(obj.Shape): | |
| if sym: | |
| s1 = n1 | |
| s2 = n2 | |
| else: | |
| s1 = obj.Shape | |
| s2 = newwire | |
| if s1 and s2: | |
| w1 = s1.Edges | |
| w2 = s2.Edges | |
| w3 = Part.LineSegment(s1.Vertexes[0].Point, s2.Vertexes[0].Point).toShape() | |
| w4 = Part.LineSegment(s1.Vertexes[-1].Point, s2.Vertexes[-1].Point).toShape() | |
| newobj = App.ActiveDocument.addObject("Part::Feature", "Offset") | |
| newobj.Shape = Part.Face(Part.Wire(w1 + [w3] + w2 + [w4])) | |
| else: | |
| print("Draft.offset: Unable to bind wires") | |
| else: | |
| newobj = App.ActiveDocument.addObject("Part::Feature", "Offset") | |
| newobj.Shape = Part.Face(obj.Shape.Wires[0]) | |
| if not copy: | |
| delete = obj.Name | |
| elif copy: | |
| newobj = None | |
| if sym: | |
| return None | |
| if utils.get_type(obj) == "Wire": | |
| if p: | |
| newobj = make_wire(p) | |
| newobj.Closed = obj.Closed | |
| elif newwire: | |
| newobj = App.ActiveDocument.addObject("Part::Feature", "Offset") | |
| newobj.Shape = newwire | |
| else: | |
| print("Draft.offset: Unable to duplicate this object") | |
| elif utils.get_type(obj) == "Rectangle": | |
| if p: | |
| length, height, plac = getRect(p, obj) | |
| newobj = make_rectangle(length, height, plac) | |
| elif newwire: | |
| newobj = App.ActiveDocument.addObject("Part::Feature", "Offset") | |
| newobj.Shape = newwire | |
| else: | |
| print("Draft.offset: Unable to duplicate this object") | |
| elif utils.get_type(obj) == "Circle": | |
| pl = obj.Placement | |
| newobj = make_circle(delta) | |
| newobj.FirstAngle = obj.FirstAngle | |
| newobj.LastAngle = obj.LastAngle | |
| newobj.Placement = pl | |
| elif utils.get_type(obj) == "Polygon": | |
| pl = obj.Placement | |
| newobj = make_polygon(obj.FacesNumber) | |
| newobj.Radius = getRadius(obj, delta) | |
| newobj.DrawMode = obj.DrawMode | |
| newobj.Placement = pl | |
| elif utils.get_type(obj) == "BSpline": | |
| newobj = make_bspline(delta) | |
| newobj.Closed = obj.Closed | |
| else: | |
| # try to offset anyway | |
| try: | |
| if p: | |
| newobj = make_wire(p) | |
| newobj.Closed = DraftGeomUtils.isReallyClosed(obj.Shape) | |
| except Part.OCCError: | |
| pass | |
| if (not newobj) and newwire: | |
| newobj = App.ActiveDocument.addObject("Part::Feature", "Offset") | |
| newobj.Shape = newwire | |
| if not newobj: | |
| print("Draft.offset: Unable to create an offset") | |
| if newobj: | |
| gui_utils.formatObject(newobj, obj) | |
| else: | |
| newobj = None | |
| if sym: | |
| return None | |
| if utils.get_type(obj) == "Wire": | |
| if obj.Base or obj.Tool: | |
| App.Console.PrintWarning("Warning: object history removed\n") | |
| obj.Base = None | |
| obj.Tool = None | |
| obj.Placement = App.Placement() # p points are in the global coordinate system | |
| obj.Points = p | |
| elif utils.get_type(obj) == "BSpline": | |
| # print(delta) | |
| obj.Points = delta | |
| # print("done") | |
| elif utils.get_type(obj) == "Rectangle": | |
| length, height, plac = getRect(p, obj) | |
| obj.Placement = plac | |
| obj.Length = length | |
| obj.Height = height | |
| elif utils.get_type(obj) == "Circle": | |
| obj.Radius = delta | |
| elif utils.get_type(obj) == "Polygon": | |
| obj.Radius = getRadius(obj, delta) | |
| elif utils.get_type(obj) == "Part": | |
| print("unsupported object") # TODO | |
| newobj = obj | |
| if copy and params.get_param("selectBaseObjects"): | |
| gui_utils.select(obj) | |
| else: | |
| gui_utils.select(newobj) | |
| if delete: | |
| App.ActiveDocument.removeObject(delete) | |
| return newobj | |
| ## @} | |