Well motivated mathematical insights combined with interactive graphics. Very interesting, indeed.Kunda1 wrote:Soft segway: Just a little historical context: The history of Bézier curves
Sketcher: Bezier curves
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Be nice to others! Respect the FreeCAD code of conduct!
Re: Sketcher: Bezier curves
A Sketcher Lecture with in-depth information is available in English, auf Deutsch, en français, en español.
- microelly2
- Veteran
- Posts: 4688
- Joined: Tue Nov 12, 2013 4:06 pm
- Contact:
Re: Sketcher: Bezier curves
Is there a way to execute the Sketcher BSpline Tools "Show/Hide XYZ" commands by a python method?
Re: Sketcher: Bezier curves
Untested, no access to FreeCAD ATM (I just copy the code from Github c++ and give you a link on how to use that info):microelly2 wrote: ↑Fri Apr 06, 2018 7:57 pm Is there a way to execute the Sketcher BSpline Tools "Show/Hide XYZ" commands by a python method?
ParameterGrp::handle hGrpsk = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Sketcher/General");
hGrpsk->GetBool("BSplineDegreeVisible", true)
hGrpsk->GetBool("BSplineControlPolygonVisible", true)
hGrpsk->GetBool("BSplineCombVisible", true)
hGrpsk->GetBool("BSplineKnotMultiplicityVisible", true)
This you have to put into Python syntax:
https://forum.freecadweb.org/viewtopic. ... 17#p225077
Hope it helps!
- microelly2
- Veteran
- Posts: 4688
- Joined: Tue Nov 12, 2013 4:06 pm
- Contact:
Re: Sketcher: Bezier curves
Thanks you. That opens the door.
- microelly2
- Veteran
- Posts: 4688
- Joined: Tue Nov 12, 2013 4:06 pm
- Contact:
Re: Sketcher: Bezier curves
because Bezier curves are easier to place than BSplines here a demo how a Bezier can work.
Endpoints of the Bezier Curves can be places exact using common Sketcher constraints
tangent direction and force is done by tangent helper points.
Endpoints of the Bezier Curves can be places exact using common Sketcher constraints
tangent direction and force is done by tangent helper points.
Re: Sketcher: Bezier curves
You are just amazing! Am I wrong that you posted another video to G+ which had the typical levers of Bezièrs like the ones of inkscape?microelly2 wrote: ↑Fri Apr 20, 2018 1:58 pm because Bezier curves are easier to place than BSplines here a demo how a Bezier can work.
Endpoints of the Bezier Curves can be places exact using common Sketcher constraints
tangent direction and force is done by tangent helper points.
When coding the current B-Spline functionality, I did thought of creating more tools to handle these curves. Eventually I will give it another go to B-Splines.
Regarding your video, could you please explain with a little bit more of detail what I am seeing and how it is implemented?
I mean:
1. I see there is a first sketch which what I think is a periodic B-Spline. Am I right?
2. I see a second sketch with lines, which you are somehow using to modify the sketch with the periodic B-Spline. Could you elaborate a little bit on the "how"?
My take is that there are two ways of implementing Béziers in the sketcher, as "tools" operating on B-Splines, or as native types. I have procrastinated to implement them as native types because it involves quite a lot of work (nothing that can not be done). I have not-well-thought-ideas of using "tools" to operate on B-Splines, which could be external tools, new constraints (effecting a bezier-ization of a bspline) or the like. But I do not want just to offer something that is not flexible enough (if the only right way is native support, then I will have to eventually stop procrastinating). That is why I am asking
- microelly2
- Veteran
- Posts: 4688
- Joined: Tue Nov 12, 2013 4:06 pm
- Contact:
Re: Sketcher: Bezier curves
I have implemented it all as Sketcher Python objects. It would be nice to have it all sometime as core functionality in sketcher.
I still need the weekend to do more tests and optimize the methods. Then I will describe what I have done.
here ist the use case
I use a constrainted closed polygon inside the sketcher. The result shape (yellow curve) is calculated on top of the sketch. It is a bspline, but not inside the sketcher. I wanted to hold the sketch as simple as possible, so inside the sketch only the needed constraints are stored.
I still need some methods to hide/unhide special groups of constraints on demand.
I still need the weekend to do more tests and optimize the methods. Then I will describe what I have done.
here ist the use case
I use a constrainted closed polygon inside the sketcher. The result shape (yellow curve) is calculated on top of the sketch. It is a bspline, but not inside the sketcher. I wanted to hold the sketch as simple as possible, so inside the sketch only the needed constraints are stored.
I still need some methods to hide/unhide special groups of constraints on demand.
Re: Sketcher: Bezier curves
That would be really great to have the inkscape like handles. Currently I prefer to edit Beziers in inkscape and import them to FreeCAD .abdullah wrote: ↑Sat Apr 21, 2018 9:59 am Am I wrong that you posted another video to G+ which had the typical levers of Bezièrs like the ones of inkscape?
When coding the current B-Spline functionality, I did thought of creating more tools to handle these curves. Eventually I will give it another go to B-Splines.
A Sketcher Lecture with in-depth information is available in English, auf Deutsch, en français, en español.
- microelly2
- Veteran
- Posts: 4688
- Joined: Tue Nov 12, 2013 4:06 pm
- Contact:
Re: Sketcher: Bezier curves
That will be possible
for the poles there can be 3 states of constraints
parallel and symmetric constraints for tangent indicator --> symmetric point
no constraint --> hard corner
parallel constraint tangent indicator --> tangent
- microelly2
- Veteran
- Posts: 4688
- Joined: Tue Nov 12, 2013 4:06 pm
- Contact:
Re: Sketcher: Bezier curves
Code: Select all
# -*- coding: utf-8 -*-
#-------------------------------------------------
#-- create a sketch for a closed bezier curves chain
#--
#-- microelly 2018 0.1
#--
#-- GNU Lesser General Public License (LGPL)
#-------------------------------------------------
import FreeCAD,FreeCADGui,Sketcher,Part
App = FreeCAD
Gui = FreeCADGui
import numpy as np
import time
import random
class FeaturePython:
''' basic defs'''
def __init__(self, obj):
obj.Proxy = self
self.Object = obj
def attach(self, vobj):
self.Object = vobj.Object
def claimChildren(self):
return self.Object.Group
def __getstate__(self):
return None
def __setstate__(self, state):
return None
class ViewProvider:
''' basic defs '''
def __init__(self, obj):
obj.Proxy = self
self.Object = obj
def __getstate__(self):
return None
def __setstate__(self, state):
return None
def setupContextMenu(self, obj, menu):
menu.clear()
action = menu.addAction("MyMethod #1")
action.triggered.connect(lambda:self.methodA(obj.Object))
action = menu.addAction("MyMethod #2")
menu.addSeparator()
action.triggered.connect(lambda:self.methodB(obj.Object))
action = menu.addAction("Edit Sketch")
action.triggered.connect(lambda:self.myedit(obj.Object))
def myedit(self,obj):
self.methodB(None)
Gui.activeDocument().setEdit(obj.Name)
obj.ViewObject.show()
self.methodA(None)
def methodA(self,obj):
print "my Method A"
FreeCAD.activeDocument().recompute()
def methodB(self,obj):
print "my method B"
FreeCAD.activeDocument().recompute()
def methodC(self,obj):
print "my method C"
FreeCAD.activeDocument().recompute()
def unsetEdit(self,vobj,mode=0):
self.methodC(None)
def doubleClicked(self,vobj):
print "double clicked"
self.myedit(vobj.Object)
print "Ende double clicked"
def getNamedConstraint(sketch,name):
'''get the index of a constraint name'''
for i,c in enumerate (sketch.Constraints):
if c.Name==name: return i
print ('Constraint name "'+name+'" not in ' +sketch.Label)
raise Exception ('Constraint name "'+name+'" not in ' + sketch.Label)
def clearReportView(name):
from PySide import QtGui
mw=Gui.getMainWindow()
r=mw.findChild(QtGui.QTextEdit, "Report view")
r.clear()
import time
now = time.ctime(int(time.time()))
App.Console.PrintWarning("Cleared Report view " +str(now)+" by " + name+"\n")
##\endcond
class BezierSketch(FeaturePython):
'''Sketch Object with Python for Bezier Curve'''
##\cond
def __init__(self, obj, icon='/home/thomas/.FreeCAD/Mod/freecad-nurbs/icons/draw.svg'):
obj.Proxy = self
self.Type = self.__class__.__name__
self.obj2 = obj
self.aa = None
obj.addProperty("App::PropertyInteger",'polescount',).polescount=12
obj.addProperty("App::PropertyBool",'init')
ViewProvider(obj.ViewObject)
##\endcond
def execute(proxy,obj):
obj.Shape=run(obj)
def run(sk):
gc=sk.GeometryCount
ap=gc/3
print ("geometry count, poles, constraints count",gc,ap,sk.ConstraintCount)
try:
if sk.init:
if sk.ConstraintCount <= 150:
for i in range(ap-1):
rc=sk.addConstraint(Sketcher.Constraint('Parallel',3*i+3,3*i+2))
# sk.setVirtualSpace(rc, True)
sk.solve()
rc=sk.addConstraint(Sketcher.Constraint('Parallel',gc-1,0))
# sk.setVirtualSpace(rc, True)
sk.init=False
for i in range(90):
# must become parameteric, depends on the number sk.polescount
#if i in [2,3,8,9,15,16,]: # for 3
# if i in [0,1,6,7,13,14,19,20]: # for 5
if i in [0,1, 6,7, 13,14, 20,21, 27,28, 34,35, 41,42, 47,48 ]: # for 7
sk.setDriving(i,False)
sk.setVirtualSpace(i, True)
jj=sk.addConstraint(Sketcher.Constraint('Distance',0,10))
sk.setDriving(jj,False)
sk.setVirtualSpace(jj, True)
jj=sk.addConstraint(Sketcher.Constraint('Distance',20,10))
sk.setDriving(jj,False)
sk.setVirtualSpace(jj, True)
print "done"
except: pass
# for c in range(sk.ConstraintCount):
# sk.setVirtualSpace(c, True)
try:
#poles=[ sk.getPoint(i,1) +FreeCAD.Vector(0,0,random.random()*2000) for i in range(sk.polescount)]
#poles=[ sk.getPoint(i,1) +FreeCAD.Vector(0,0,0) for i in range(sk.polescount*3)]
# gleich doppelte Punkte
poles=[]
for i in range(sk.polescount*3):
p=sk.getPoint(i,1)
if i%3== 0:
poles += [p,p,p] # corner pole -- multiplicity 3
else:
poles += [p] # tangent pole
cc=Part.BSplineCurve(poles+[poles[0]])
return cc.toShape()
except:
return Part.Shape()
def init_bezierring(sk,count=5,source=None):
if source <> None:
ptsa=source.Shape.Wires[0].discretize(count*2*10)
ptsb=[]
# read some exact point p for the pole and a approx tangent p2-p, pv-p for the tangent indicators
for n in range(count):
p=ptsa[2*n*10]
p2=p+ (ptsa[2*n*10+1]-p).normalize()*10
pv=p+((p-p2).normalize())*(10)
if n==0:
last=pv
ptsb += [p,p2]
else:
ptsb += [pv,p,p2]
# the tangent from the first pole
ptsb += [last]
# map from xz scan to xy sketch
pts=[FreeCAD.Vector(p.x,p.z,0) for p in ptsb]
else: # a generated circle with some noise
r=100
pts=[]
for i in range(count):
p=FreeCAD.Vector(r*np.cos(2*i*np.pi/count),r*np.sin(2*i*np.pi/count),0)
p2=FreeCAD.Vector(r*np.cos((2*i+1)*np.pi/count),r*np.sin((2*i+1)*np.pi/count),0)
p2 += FreeCAD.Vector((0.5-random.random())*0.2*r,(0.5-random.random())*0.2*r)
pm=(p+p2)*0.5
pts +=[p,pm,p2]
for i in range(count):
if i <> 0: # connect to the last segment with a connector line
lc=sk.addGeometry(Part.LineSegment(pts[3*i-1],pts[3*i]),False)
sk.addConstraint(Sketcher.Constraint('Coincident',lb,2,lc,1))
la=sk.addGeometry(Part.LineSegment(pts[3*i],pts[3*i+1]),False)
lb=sk.addGeometry(Part.LineSegment(pts[3*i+1],pts[3*i+2]),False)
if 1: # avoid moving of points
p2=sk.getPoint(lb,1)
cc=sk.addConstraint(Sketcher.Constraint('DistanceX',lb,1,p2.x))
sk.addConstraint(Sketcher.Constraint('DistanceY',lb,1,p2.y))
sk.renameConstraint(cc, u'aa ' + str(i))
p2=sk.getPoint(la,1)
cc=sk.addConstraint(Sketcher.Constraint('DistanceX',la,1,p2.x))
sk.addConstraint(Sketcher.Constraint('DistanceY',la,1,p2.y))
sk.renameConstraint(cc, u'bb ' + str(i))
# blocking does not work (unsolvable by sketcher) why?
# sk.addConstraint(Sketcher.Constraint('Block',lb))
sk.addConstraint(Sketcher.Constraint('Coincident',la,2,lb,1))
if i <> 0: # connect connector line to the new created segment
sk.addConstraint(Sketcher.Constraint('Coincident',lc,2,la,1))
# close the figure
# the last connector
la=sk.addGeometry(Part.LineSegment(pts[3*i],pts[0]),False)
p2=sk.getPoint(la,1)
cc=sk.addConstraint(Sketcher.Constraint('DistanceX',la,1,p2.x))
sk.addConstraint(Sketcher.Constraint('DistanceY',la,1,p2.y))
sk.renameConstraint(cc, u'cc ' + str(i))
# connect head and foot
sk.addConstraint(Sketcher.Constraint('Coincident',lb,2,la,1))
sk.addConstraint(Sketcher.Constraint('Coincident',la,2,0,1))
def createBezierSketch(name="BezierRing",source=None):
if source <> None:
name="Sk_"+source.Label+'_'
obj = FreeCAD.ActiveDocument.addObject("Sketcher::SketchObjectPython",name)
BezierSketch(obj)
obj.polescount=7
init_bezierring(obj,count=obj.polescount,source=source)
obj.init=True
return obj
def createBezierRingSketch(name="BezierRing",source=None):
return createBezierSketch(name,source)
if __name__ == '__main__':
createBezierRingSketch()