Draft: split offset from Draft.py
.
This commit is contained in:
committed by
Yorik van Havre
parent
ff1d0587ff
commit
9eb59414c1
@@ -62,6 +62,7 @@ SET(Draft_functions
|
||||
draftfunctions/__init__.py
|
||||
draftfunctions/join.py
|
||||
draftfunctions/move.py
|
||||
draftfunctions/offset.py
|
||||
draftfunctions/rotate.py
|
||||
draftfunctions/scale.py
|
||||
draftfunctions/split.py
|
||||
|
||||
@@ -194,6 +194,8 @@ from draftfunctions.join import join_two_wires as joinTwoWires
|
||||
|
||||
from draftfunctions.split import split
|
||||
|
||||
from draftfunctions.offset import offset
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Draft objects
|
||||
#---------------------------------------------------------------------------
|
||||
@@ -685,192 +687,6 @@ def rotateEdge(object, edge_index, angle, center, axis):
|
||||
rotateVertex(object, edge_index+1, angle, center, axis)
|
||||
|
||||
|
||||
|
||||
|
||||
def offset(obj,delta,copy=False,bind=False,sym=False,occ=False):
|
||||
"""offset(object,delta,[copymode],[bind]): offsets the given wire by
|
||||
applying the given delta Vector to its first vertex. If copymode is
|
||||
True, another object is created, otherwise the same object gets
|
||||
offset. 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
|
||||
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. If offsetting a
|
||||
BSpline, the delta must not be a Vector but a list of Vectors, one for
|
||||
each node of the spline."""
|
||||
import Part, DraftGeomUtils
|
||||
newwire = None
|
||||
delete = None
|
||||
|
||||
if getType(obj) in ["Sketch","Part"]:
|
||||
copy = True
|
||||
print("the offset tool is currently unable to offset a non-Draft object directly - Creating a copy")
|
||||
|
||||
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 getType(obj) == "Circle":
|
||||
pass
|
||||
elif getType(obj) == "BSpline":
|
||||
pass
|
||||
else:
|
||||
if sym:
|
||||
d1 = 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 = FreeCAD.ActiveDocument.addObject("Part::Feature","Offset")
|
||||
newobj.Shape = DraftGeomUtils.offsetWire(obj.Shape,delta,occ=True)
|
||||
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 = FreeCAD.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 = FreeCAD.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 getType(obj) == "Wire":
|
||||
if p:
|
||||
newobj = makeWire(p)
|
||||
newobj.Closed = obj.Closed
|
||||
elif newwire:
|
||||
newobj = FreeCAD.ActiveDocument.addObject("Part::Feature","Offset")
|
||||
newobj.Shape = newwire
|
||||
else:
|
||||
print("Draft.offset: Unable to duplicate this object")
|
||||
elif getType(obj) == "Rectangle":
|
||||
if p:
|
||||
length,height,plac = getRect(p,obj)
|
||||
newobj = makeRectangle(length,height,plac)
|
||||
elif newwire:
|
||||
newobj = FreeCAD.ActiveDocument.addObject("Part::Feature","Offset")
|
||||
newobj.Shape = newwire
|
||||
else:
|
||||
print("Draft.offset: Unable to duplicate this object")
|
||||
elif getType(obj) == "Circle":
|
||||
pl = obj.Placement
|
||||
newobj = makeCircle(delta)
|
||||
newobj.FirstAngle = obj.FirstAngle
|
||||
newobj.LastAngle = obj.LastAngle
|
||||
newobj.Placement = pl
|
||||
elif getType(obj) == "Polygon":
|
||||
pl = obj.Placement
|
||||
newobj = makePolygon(obj.FacesNumber)
|
||||
newobj.Radius = getRadius(obj,delta)
|
||||
newobj.DrawMode = obj.DrawMode
|
||||
newobj.Placement = pl
|
||||
elif getType(obj) == "BSpline":
|
||||
newobj = makeBSpline(delta)
|
||||
newobj.Closed = obj.Closed
|
||||
else:
|
||||
# try to offset anyway
|
||||
try:
|
||||
if p:
|
||||
newobj = makeWire(p)
|
||||
newobj.Closed = obj.Shape.isClosed()
|
||||
except Part.OCCError:
|
||||
pass
|
||||
if not(newobj) and newwire:
|
||||
newobj = FreeCAD.ActiveDocument.addObject("Part::Feature","Offset")
|
||||
newobj.Shape = newwire
|
||||
else:
|
||||
print("Draft.offset: Unable to create an offset")
|
||||
if newobj:
|
||||
formatObject(newobj,obj)
|
||||
else:
|
||||
newobj = None
|
||||
if sym: return None
|
||||
if getType(obj) == "Wire":
|
||||
if obj.Base or obj.Tool:
|
||||
FreeCAD.Console.PrintWarning("Warning: object history removed\n")
|
||||
obj.Base = None
|
||||
obj.Tool = None
|
||||
obj.Points = p
|
||||
elif getType(obj) == "BSpline":
|
||||
#print(delta)
|
||||
obj.Points = delta
|
||||
#print("done")
|
||||
elif getType(obj) == "Rectangle":
|
||||
length,height,plac = getRect(p,obj)
|
||||
obj.Placement = plac
|
||||
obj.Length = length
|
||||
obj.Height = height
|
||||
elif getType(obj) == "Circle":
|
||||
obj.Radius = delta
|
||||
elif getType(obj) == "Polygon":
|
||||
obj.Radius = getRadius(obj,delta)
|
||||
elif getType(obj) == 'Part':
|
||||
print("unsupported object") # TODO
|
||||
newobj = obj
|
||||
if copy and getParam("selectBaseObjects",False):
|
||||
select(newobj)
|
||||
else:
|
||||
select(obj)
|
||||
if delete:
|
||||
FreeCAD.ActiveDocument.removeObject(delete)
|
||||
return newobj
|
||||
|
||||
def draftify(objectslist,makeblock=False,delete=True):
|
||||
"""draftify(objectslist,[makeblock],[delete]): turns each object of the given list
|
||||
(objectslist can also be a single object) into a Draft parametric
|
||||
|
||||
246
src/Mod/Draft/draftfunctions/offset.py
Normal file
246
src/Mod/Draft/draftfunctions/offset.py
Normal file
@@ -0,0 +1,246 @@
|
||||
# ***************************************************************************
|
||||
# * 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 *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
"""This module provides the code for Draft offset function.
|
||||
"""
|
||||
## @package offset
|
||||
# \ingroup DRAFT
|
||||
# \brief This module provides the code for Draft offset function.
|
||||
|
||||
import math
|
||||
|
||||
import FreeCAD as App
|
||||
|
||||
import DraftVecUtils
|
||||
|
||||
import draftutils.gui_utils as gui_utils
|
||||
import draftutils.utils as utils
|
||||
|
||||
from draftmake.make_copy import make_copy
|
||||
|
||||
from draftmake.make_rectangle import makeRectangle
|
||||
from draftmake.make_wire import makeWire
|
||||
from draftmake.make_polygon import makePolygon
|
||||
from draftmake.make_circle import makeCircle
|
||||
from draftmake.make_bspline import makeBSpline
|
||||
|
||||
|
||||
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 utils.get_type(obj) in ["Sketch","Part"]:
|
||||
copy = True
|
||||
print("the offset tool is currently unable to offset a non-Draft object directly - Creating a copy")
|
||||
|
||||
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 = makeWire(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 = makeRectangle(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 = makeCircle(delta)
|
||||
newobj.FirstAngle = obj.FirstAngle
|
||||
newobj.LastAngle = obj.LastAngle
|
||||
newobj.Placement = pl
|
||||
elif utils.get_type(obj) == "Polygon":
|
||||
pl = obj.Placement
|
||||
newobj = makePolygon(obj.FacesNumber)
|
||||
newobj.Radius = getRadius(obj,delta)
|
||||
newobj.DrawMode = obj.DrawMode
|
||||
newobj.Placement = pl
|
||||
elif utils.get_type(obj) == "BSpline":
|
||||
newobj = makeBSpline(delta)
|
||||
newobj.Closed = obj.Closed
|
||||
else:
|
||||
# try to offset anyway
|
||||
try:
|
||||
if p:
|
||||
newobj = makeWire(p)
|
||||
newobj.Closed = obj.Shape.isClosed()
|
||||
except Part.OCCError:
|
||||
pass
|
||||
if not(newobj) and newwire:
|
||||
newobj = App.ActiveDocument.addObject("Part::Feature","Offset")
|
||||
newobj.Shape = newwire
|
||||
else:
|
||||
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.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 utils.get_param("selectBaseObjects",False):
|
||||
gui_utils.select(newobj)
|
||||
else:
|
||||
gui_utils.select(obj)
|
||||
if delete:
|
||||
App.ActiveDocument.removeObject(delete)
|
||||
return newobj
|
||||
Reference in New Issue
Block a user