Draft Bezier Curve: implemented Continuity Property
Draft: allow continuity on closed Bezier curves Draft: BezCurve bugfixes - smoothBezCurve - edit mode - avoid splitting points into segments as long as degree is zero - increase the continuity when closing curve - closed berzier curves - Catch modifications of continuity of first and last knot on open curves
This commit is contained in:
parent
6f8c1c61b7
commit
2dfabfdcb5
|
@ -853,6 +853,7 @@ def makeBezCurve(pointslist,closed=False,placement=None,support=None,Degree=None
|
|||
Part.BezierCurve().MaxDegree)
|
||||
obj.Closed = closed
|
||||
obj.Support = support
|
||||
obj.Proxy.resetcontinuity(obj)
|
||||
if placement: obj.Placement = placement
|
||||
if gui:
|
||||
_ViewProviderWire(obj.ViewObject)
|
||||
|
@ -3971,30 +3972,60 @@ class _BezCurve(_DraftObject):
|
|||
"The points of the Bezier curve")
|
||||
obj.addProperty("App::PropertyInteger","Degree","Draft",
|
||||
"The degree of the Bezier function")
|
||||
obj.addProperty("App::PropertyIntegerList","Continuity","Draft",
|
||||
"Continuity")
|
||||
obj.addProperty("App::PropertyBool","Closed","Draft",
|
||||
"If the Bezier curve should be closed or not")
|
||||
obj.Closed = False
|
||||
obj.Degree = 3
|
||||
obj.Continuity = []
|
||||
#obj.setEditorMode("Degree",2)#hide
|
||||
obj.setEditorMode("Continuity",1)#ro
|
||||
|
||||
def execute(self, fp):
|
||||
self.createGeometry(fp)
|
||||
|
||||
|
||||
def _segpoleslst(self,fp):
|
||||
"""split the points into segments"""
|
||||
if not fp.Closed and len(fp.Points) >= 2: #allow lower degree segement
|
||||
poles=fp.Points[1:]
|
||||
elif fp.Closed and len(fp.Points) >= fp.Degree: #drawable
|
||||
#poles=fp.Points[1:(fp.Degree*(len(fp.Points)//fp.Degree))]+fp.Points[0:1]
|
||||
poles=fp.Points[1:]+fp.Points[0:1]
|
||||
else:
|
||||
poles=[]
|
||||
return [poles[x:x+fp.Degree] for x in \
|
||||
xrange(0, len(poles), (fp.Degree or 1))]
|
||||
|
||||
def resetcontinuity(self,fp):
|
||||
fp.Continuity = [0]*(len(self._segpoleslst(fp))-1+1*fp.Closed)
|
||||
#nump= len(fp.Points)-1+fp.Closed*1
|
||||
#numsegments = (nump // fp.Degree) + 1 * (nump % fp.Degree > 0) -1
|
||||
#fp.Continuity = [0]*numsegments
|
||||
|
||||
def onChanged(self, fp, prop):
|
||||
if prop in ["Points","Degree", "Closed"]:
|
||||
if prop == 'Closed': # if remove the last entry when curve gets opened
|
||||
oldlen = len(fp.Continuity)
|
||||
newlen = (len(self._segpoleslst(fp))-1+1*fp.Closed)
|
||||
if oldlen > newlen:
|
||||
fp.Continuity = fp.Continuity[:newlen]
|
||||
if oldlen < newlen:
|
||||
fp.Continuity = fp.Continuity + [0]*(newlen-oldlen)
|
||||
if hasattr(fp,'Closed') and fp.Closed and prop in ['Points','Degree','Closed'] and\
|
||||
len(fp.Points) % fp.Degree: # the curve editing tools can't handle extra points
|
||||
fp.Points=fp.Points[:(fp.Degree*(len(fp.Points)//fp.Degree))] #for closed curves
|
||||
if prop in ["Degree"] and fp.Degree >= 1: #reset Continuity
|
||||
self.resetcontinuity(fp)
|
||||
if prop in ["Points","Degree","Continuity","Closed"]:
|
||||
self.createGeometry(fp)
|
||||
|
||||
|
||||
def createGeometry(self,fp):
|
||||
import Part
|
||||
plm = fp.Placement
|
||||
if fp.Points:
|
||||
startpoint=fp.Points[0]
|
||||
poles=fp.Points[1:]
|
||||
if fp.Closed and (len(fp.Points) > 2):
|
||||
poles.append(fp.Points[0])
|
||||
segpoleslst=[poles[x:x+fp.Degree] for x in \
|
||||
xrange(0, len(poles), fp.Degree)]
|
||||
edges = []
|
||||
for segpoles in segpoleslst:
|
||||
for segpoles in self._segpoleslst(fp):
|
||||
# if len(segpoles) == fp.Degree # would skip additional poles
|
||||
c = Part.BezierCurve() #last segment may have lower degree
|
||||
c.increase(len(segpoles))
|
||||
|
|
|
@ -283,6 +283,7 @@ class DraftToolBar:
|
|||
|
||||
self.addButton = self._pushbutton("addButton", self.layout, icon="Draft_AddPoint", width=22, checkable=True)
|
||||
self.delButton = self._pushbutton("delButton", self.layout, icon="Draft_DelPoint", width=22, checkable=True)
|
||||
self.sharpButton = self._pushbutton("sharpButton", self.layout, icon="Draft_BezSharpNode", width=22, checkable=True)
|
||||
self.tangentButton = self._pushbutton("tangentButton", self.layout, icon="Draft_BezTanNode", width=22, checkable=True)
|
||||
self.symmetricButton = self._pushbutton("symmetricButton", self.layout, icon="Draft_BezSymNode", width=22, checkable=True)
|
||||
|
||||
|
@ -373,6 +374,7 @@ class DraftToolBar:
|
|||
QtCore.QObject.connect(self.offsetValue,QtCore.SIGNAL("returnPressed()"),self.validatePoint)
|
||||
QtCore.QObject.connect(self.addButton,QtCore.SIGNAL("toggled(bool)"),self.setAddMode)
|
||||
QtCore.QObject.connect(self.delButton,QtCore.SIGNAL("toggled(bool)"),self.setDelMode)
|
||||
QtCore.QObject.connect(self.sharpButton,QtCore.SIGNAL("toggled(bool)"),self.setSharpMode)
|
||||
QtCore.QObject.connect(self.tangentButton,QtCore.SIGNAL("toggled(bool)"),self.setTangentMode)
|
||||
QtCore.QObject.connect(self.symmetricButton,QtCore.SIGNAL("toggled(bool)"),self.setSymmetricMode)
|
||||
QtCore.QObject.connect(self.finishButton,QtCore.SIGNAL("pressed()"),self.finish)
|
||||
|
@ -450,6 +452,7 @@ class DraftToolBar:
|
|||
style = "#constrButton:Checked {background-color: "
|
||||
style += self.getDefaultColor("constr",rgb=True)+" } "
|
||||
style += "#addButton:Checked, #delButton:checked, "
|
||||
style += "#sharpButton:Checked, "
|
||||
style += "#tangentButton:Checked, #symmetricButton:checked {"
|
||||
style += "background-color: rgb(20,100,250) }"
|
||||
self.baseWidget.setStyleSheet(style)
|
||||
|
@ -482,6 +485,7 @@ class DraftToolBar:
|
|||
self.occOffset.setText(translate("draft", "&OCC-style offset"))
|
||||
self.addButton.setToolTip(translate("draft", "Add points to the current object"))
|
||||
self.delButton.setToolTip(translate("draft", "Remove points from the current object"))
|
||||
self.sharpButton.setToolTip(translate("draft", "Make Bezier node sharp"))
|
||||
self.tangentButton.setToolTip(translate("draft", "Make Bezier node tangent"))
|
||||
self.symmetricButton.setToolTip(translate("draft", "Make Bezier node symmetric"))
|
||||
self.undoButton.setText(translate("draft", "&Undo"))
|
||||
|
@ -679,6 +683,7 @@ class DraftToolBar:
|
|||
self.finishButton.hide()
|
||||
self.addButton.hide()
|
||||
self.delButton.hide()
|
||||
self.sharpButton.hide()
|
||||
self.tangentButton.hide()
|
||||
self.symmetricButton.hide()
|
||||
self.undoButton.hide()
|
||||
|
@ -810,6 +815,7 @@ class DraftToolBar:
|
|||
self.addButton.show()
|
||||
self.delButton.show()
|
||||
if mode == 'BezCurve':
|
||||
self.sharpButton.show()
|
||||
self.tangentButton.show()
|
||||
self.symmetricButton.show()
|
||||
self.finishButton.show()
|
||||
|
@ -817,6 +823,7 @@ class DraftToolBar:
|
|||
# always start Edit with buttons unchecked
|
||||
self.addButton.setChecked(False)
|
||||
self.delButton.setChecked(False)
|
||||
self.sharpButton.setChecked(False)
|
||||
self.tangentButton.setChecked(False)
|
||||
self.symmetricButton.setChecked(False)
|
||||
|
||||
|
@ -848,6 +855,7 @@ class DraftToolBar:
|
|||
self.delButton.setEnabled(mode)
|
||||
|
||||
def setBezEditButtons(self,mode):
|
||||
self.sharpButton.setEnabled(mode)
|
||||
self.tangentButton.setEnabled(mode)
|
||||
self.symmetricButton.setEnabled(mode)
|
||||
|
||||
|
@ -1378,22 +1386,33 @@ class DraftToolBar:
|
|||
if self.addButton.isChecked():
|
||||
self.delButton.setChecked(False)
|
||||
self.symmetricButton.setChecked(False)
|
||||
self.sharpButton.setChecked(False)
|
||||
self.tangentButton.setChecked(False)
|
||||
|
||||
def setDelMode(self,bool):
|
||||
if self.delButton.isChecked():
|
||||
self.addButton.setChecked(False)
|
||||
self.symmetricButton.setChecked(False)
|
||||
self.sharpButton.setChecked(False)
|
||||
self.tangentButton.setChecked(False)
|
||||
|
||||
def setSharpMode(self,bool):
|
||||
if self.sharpButton.isChecked():
|
||||
self.tangentButton.setChecked(False)
|
||||
self.symmetricButton.setChecked(False)
|
||||
self.addButton.setChecked(False)
|
||||
self.delButton.setChecked(False)
|
||||
|
||||
def setTangentMode(self,bool):
|
||||
if self.tangentButton.isChecked():
|
||||
self.sharpButton.setChecked(False)
|
||||
self.symmetricButton.setChecked(False)
|
||||
self.addButton.setChecked(False)
|
||||
self.delButton.setChecked(False)
|
||||
|
||||
def setSymmetricMode(self,bool):
|
||||
if self.symmetricButton.isChecked():
|
||||
self.sharpButton.setChecked(False)
|
||||
self.tangentButton.setChecked(False)
|
||||
self.addButton.setChecked(False)
|
||||
self.delButton.setChecked(False)
|
||||
|
|
|
@ -3319,6 +3319,10 @@ class Edit(Modifier):
|
|||
if 'EditNode' in info["Component"]:
|
||||
self.delPoint(int(info["Component"][8:]))
|
||||
# don't do tan/sym on DWire/BSpline!
|
||||
elif ((Draft.getType(self.obj) == "BezCurve") and
|
||||
(self.ui.sharpButton.isChecked())):
|
||||
if 'EditNode' in info["Component"]:
|
||||
self.smoothBezPoint(int(info["Component"][8:]), info, 'Sharp')
|
||||
elif ((Draft.getType(self.obj) == "BezCurve") and
|
||||
(self.ui.tangentButton.isChecked())):
|
||||
if 'EditNode' in info["Component"]:
|
||||
|
@ -3354,14 +3358,48 @@ class Edit(Modifier):
|
|||
self.obj.Closed = True
|
||||
# DNC: fix error message if edited point coinsides with one of the existing points
|
||||
if ( editPnt in pts ) == False:
|
||||
if Draft.getType(self.obj) in ["BezCurve"] and self.obj.Degree >=3 and \
|
||||
(self.editing % self.obj.Degree) == 0: #it's a knot
|
||||
if self.editing >= 1: #move left pole
|
||||
pts[self.editing-1] = pts[self.editing-1] + editPnt - pts[self.editing]
|
||||
self.trackers[self.editing-1].set(pts[self.editing-1])
|
||||
if self.editing < len(pts)-1: #move right pole
|
||||
pts[self.editing+1] = pts[self.editing+1] + editPnt - pts[self.editing]
|
||||
self.trackers[self.editing+1].set(pts[self.editing+1])
|
||||
if Draft.getType(self.obj) in ["BezCurve"]:
|
||||
knot = None
|
||||
ispole = self.editing % self.obj.Degree #
|
||||
if ispole == 0: #knot
|
||||
if self.obj.Degree >=3:
|
||||
if self.editing >= 1: #move left pole
|
||||
knotidx = self.editing if self.editing < len(pts) else 0
|
||||
pts[self.editing-1] = pts[self.editing-1] + \
|
||||
editPnt - pts[knotidx]
|
||||
self.trackers[self.editing-1].set(\
|
||||
pts[self.editing-1])
|
||||
if self.editing < len(pts)-1: #move right pole
|
||||
pts[self.editing+1] = pts[self.editing+1] + \
|
||||
editPnt - pts[self.editing]
|
||||
self.trackers[self.editing+1].set(\
|
||||
pts[self.editing+1])
|
||||
if self.editing == 0 and self.obj.Closed: # move last pole
|
||||
pts[-1] = pts [-1] + editPnt -pts[self.editing]
|
||||
self.trackers[-1].set(pts[-1])
|
||||
elif ispole == 1 and (self.editing >=2 or self.obj.Closed): #right pole
|
||||
knot = self.editing -1
|
||||
changep = self.editing -2 # -1 in case of closed curve
|
||||
elif ispole == self.obj.Degree-1 and \
|
||||
self.editing <= len(pts)-3: #left pole
|
||||
knot = self.editing +1
|
||||
changep = self.editing +2
|
||||
elif ispole == self.obj.Degree-1 and self.obj.Closed and \
|
||||
self.editing == len(pts)-1: #last pole
|
||||
knot = 0
|
||||
changep = 1
|
||||
if knot is not None: # we need to modify the oposite pole
|
||||
segment = knot / self.obj.Degree -1
|
||||
cont=self.obj.Continuity[segment] if \
|
||||
len(self.obj.Continuity) > segment else 0
|
||||
if cont == 1: #tangent
|
||||
pts[changep] = self.obj.Proxy.modifytangentpole(\
|
||||
pts[knot],editPnt,pts[changep])
|
||||
self.trackers[changep].set(pts[changep])
|
||||
elif cont ==2: #symmetric
|
||||
pts[changep] = self.obj.Proxy.modifysymmetricpole(\
|
||||
pts[knot],editPnt)
|
||||
self.trackers[changep].set(pts[changep])
|
||||
pts[self.editing] = editPnt
|
||||
self.obj.Points = pts
|
||||
self.trackers[self.editing].set(v)
|
||||
|
@ -3463,6 +3501,11 @@ class Edit(Modifier):
|
|||
pts.extend(edge.Curve.getPoles()[1:])
|
||||
if self.obj.Closed:
|
||||
pts.pop()
|
||||
c=self.obj.Continuity
|
||||
# assume we have a tangent continuity for an arbitrarily split
|
||||
# segment, unless it's linear
|
||||
cont = 1 if (self.obj.Degree >= 2) else 0
|
||||
self.obj.Continuity = c[0:edgeindex]+[cont]+c[edgeindex:]
|
||||
else:
|
||||
if ( Draft.getType(self.obj) == "Wire" ):
|
||||
if (self.obj.Closed == True):
|
||||
|
@ -3510,64 +3553,111 @@ class Edit(Modifier):
|
|||
pts.pop(point)
|
||||
self.doc.openTransaction("Edit "+self.obj.Name)
|
||||
self.obj.Points = pts
|
||||
if Draft.getType(self.obj) =="BezCurve":
|
||||
self.obj.Proxy.resetcontinuity(self.obj)
|
||||
self.doc.commitTransaction()
|
||||
self.resetTrackers()
|
||||
|
||||
def smoothBezPoint(self,point, info=None, style='Symmetric'):
|
||||
if not (Draft.getType(self.obj) == "BezCurve"): return
|
||||
style2cont = {'Sharp':0,'Tangent':1,'Symmetric':2}
|
||||
if not (Draft.getType(self.obj) == "BezCurve"):return
|
||||
if info['Component'].startswith('Edge'):
|
||||
return # didn't click control point
|
||||
pts = self.obj.Points
|
||||
deg = self.obj.Degree
|
||||
if point % deg != 0:
|
||||
if deg < 2: return
|
||||
if point % deg != 0: #point is a pole
|
||||
if deg >=3: #allow to select poles
|
||||
if point > 2 and point % deg == 1: #right pole
|
||||
if (point % deg == 1) and (point > 2 or self.obj.Closed): #right pole
|
||||
knot = point -1
|
||||
keepp = point
|
||||
changep = point -2
|
||||
elif point -3 < len(pts): #left pole
|
||||
elif point < len(pts) -3 and point % deg == deg -1: #left pole
|
||||
knot = point +1
|
||||
keepp = point
|
||||
changep = point +2
|
||||
elif point == len(pts)-1 and self.obj.Closed: #last pole
|
||||
# if the curve is closed the last pole has the last
|
||||
# index in the poits lists
|
||||
knot = 0
|
||||
keepp = point
|
||||
changep = 1
|
||||
else:
|
||||
msg(translate("draft", "Can't change Knot belonging to that pole\n"),'warning')
|
||||
msg(translate("draft", "Can't change Knot belonging to pole %d\n"%point)\
|
||||
,'warning')
|
||||
return
|
||||
if knot:
|
||||
if style == 'Tangent':
|
||||
pts[changep] = self.obj.Proxy.modifytangentpole(pts[knot],pts[keepp],\
|
||||
pts[changep])
|
||||
else:
|
||||
pts[changep] = self.obj.Proxy.modifysymmetricpole(pts[knot],pts[keepp])
|
||||
pts[changep] = self.obj.Proxy.modifytangentpole(\
|
||||
pts[knot],pts[keepp],pts[changep])
|
||||
elif style == 'Symmetric':
|
||||
pts[changep] = self.obj.Proxy.modifysymmetricpole(\
|
||||
pts[knot],pts[keepp])
|
||||
else: #sharp
|
||||
pass #
|
||||
else:
|
||||
msg(translate("draft", "Selection is not a Pole\n"),'warning')
|
||||
msg(translate("draft", "Selection is not a Knot\n"),'warning')
|
||||
return
|
||||
elif (point == 0) or (point == (len(pts)-1)):
|
||||
msg(translate("draft", "Endpoint of BezCurve can't be smoothed\n"),'warning')
|
||||
return
|
||||
else:
|
||||
if style == 'Tangent':
|
||||
else: #point is a knot
|
||||
if style == 'Sharp':
|
||||
if self.obj.Closed and point == len(pts)-1:
|
||||
knot = 0
|
||||
else:
|
||||
knot = point
|
||||
elif style == 'Tangent' and point > 0 and point < len(pts)-1:
|
||||
prev, next = self.obj.Proxy.tangentpoles(pts[point],pts[point-1],pts[point+1])
|
||||
else:
|
||||
pts[point-1] = prev
|
||||
pts[point+1] = next
|
||||
knot = point #index for continuity
|
||||
elif style == 'Symmetric' and point > 0 and point < len(pts)-1:
|
||||
prev, next = self.obj.Proxy.symmetricpoles(pts[point],pts[point-1],pts[point+1])
|
||||
pts[point-1] = prev
|
||||
pts[point+1] = next
|
||||
self.obj.Points = pts
|
||||
pts[point-1] = prev
|
||||
pts[point+1] = next
|
||||
knot = point #index for continuity
|
||||
elif self.obj.Closed and (style == 'Symmetric' or style == 'Tangent'):
|
||||
if style == 'Tangent':
|
||||
pts[1],pts[-1] = self.obj.Proxy.tangentpoles(pts[0],pts[1],pts[-1])
|
||||
elif style == 'Symmetric':
|
||||
pts[1],pts[-1] = self.obj.Proxy.symmetricpoles(pts[0],pts[1],pts[-1])
|
||||
knot = 0
|
||||
else:
|
||||
msg(translate("draft", "Endpoint of BezCurve can't be smoothed\n"),'warning')
|
||||
return
|
||||
segment = knot // deg #segment index
|
||||
newcont=self.obj.Continuity[:] #dont edit a property inplace !!!
|
||||
if not self.obj.Closed and (len(self.obj.Continuity) == segment -1 or \
|
||||
segment == 0) : pass # open curve
|
||||
elif len(self.obj.Continuity) >= segment or \
|
||||
self.obj.Closed and segment == 0 and \
|
||||
len(self.obj.Continuity) >1:
|
||||
newcont[segment-1] = style2cont.get(style)
|
||||
else: #should not happen
|
||||
FreeCAD.Console.PrintWarning('Continuity indexing error:'+\
|
||||
'point:%d deg:%d len(cont):%d' % (knot,deg,\
|
||||
len(self.obj.Continuity)))
|
||||
self.doc.openTransaction("Edit "+self.obj.Name)
|
||||
self.obj.Points = pts
|
||||
self.obj.Continuity=newcont
|
||||
self.doc.commitTransaction()
|
||||
self.resetTrackers()
|
||||
|
||||
def resetTrackersBezier(self):
|
||||
knotmarker = coin.SoMarkerSet.SQUARE_FILLED_9_9
|
||||
polemarker = coin.SoMarkerSet.CIRCLE_FILLED_9_9
|
||||
knotmarkers = (coin.SoMarkerSet.DIAMOND_FILLED_9_9,#sharp
|
||||
coin.SoMarkerSet.SQUARE_FILLED_9_9, #tangent
|
||||
coin.SoMarkerSet.HOURGLASS_FILLED_9_9) #symmetric
|
||||
polemarker = coin.SoMarkerSet.CIRCLE_FILLED_9_9 #pole
|
||||
self.trackers=[]
|
||||
cont=self.obj.Continuity
|
||||
firstknotcont = cont[-1] if (self.obj.Closed and cont) else 0
|
||||
pointswithmarkers=[(self.obj.Shape.Edges[0].Curve.\
|
||||
getPole(1),knotmarker)]
|
||||
getPole(1),knotmarkers[firstknotcont])]
|
||||
for edgeindex, edge in enumerate(self.obj.Shape.Edges):
|
||||
poles=edge.Curve.getPoles()
|
||||
pointswithmarkers.extend([(point,polemarker) for \
|
||||
point in poles[1:-1]])
|
||||
if not self.obj.Closed or len(self.obj.Shape.Edges) > edgeindex +1:
|
||||
pointswithmarkers.append((poles[-1],knotmarker))
|
||||
knotmarkeri=cont[edgeindex] if len(cont) > edgeindex else 0
|
||||
pointswithmarkers.append((poles[-1],knotmarkers[knotmarkeri]))
|
||||
for index,pwm in enumerate(pointswithmarkers):
|
||||
p,marker=pwm
|
||||
if self.pl: p = self.pl.multVec(p)
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -6,6 +6,7 @@
|
|||
<file>icons/Draft_Arc.svg</file>
|
||||
<file>icons/Draft_BSpline.svg</file>
|
||||
<file>icons/Draft_BezCurve.svg</file>
|
||||
<file>icons/Draft_BezSharpNode.svg</file>
|
||||
<file>icons/Draft_BezTanNode.svg</file>
|
||||
<file>icons/Draft_BezSymNode.svg</file>
|
||||
<file>icons/Draft_Circle.svg</file>
|
||||
|
|
304
src/Mod/Draft/Resources/icons/Draft_BezSharpNode.svg
Normal file
304
src/Mod/Draft/Resources/icons/Draft_BezSharpNode.svg
Normal file
|
@ -0,0 +1,304 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
version="1.1"
|
||||
width="64"
|
||||
height="64"
|
||||
id="svg3612">
|
||||
<defs
|
||||
id="defs3614">
|
||||
<linearGradient
|
||||
id="linearGradient3144-6">
|
||||
<stop
|
||||
id="stop3146-9"
|
||||
style="stop-color:#ffffff;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop3148-2"
|
||||
style="stop-color:#ffffff;stop-opacity:0"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3701">
|
||||
<stop
|
||||
id="stop3703"
|
||||
style="stop-color:#ffffff;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop3705"
|
||||
style="stop-color:#ffffff;stop-opacity:0"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
cx="225.26402"
|
||||
cy="672.79736"
|
||||
r="34.345188"
|
||||
fx="225.26402"
|
||||
fy="672.79736"
|
||||
id="radialGradient3688"
|
||||
xlink:href="#linearGradient3144-6"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1,0,0,0.6985294,0,202.82863)" />
|
||||
<linearGradient
|
||||
id="linearGradient3708">
|
||||
<stop
|
||||
id="stop3710"
|
||||
style="stop-color:#ffffff;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop3712"
|
||||
style="stop-color:#ffffff;stop-opacity:0"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3864-0-0">
|
||||
<stop
|
||||
id="stop3866-5-7"
|
||||
style="stop-color:#0619c0;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop3868-7-6"
|
||||
style="stop-color:#379cfb;stop-opacity:1"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3377">
|
||||
<stop
|
||||
id="stop3379"
|
||||
style="stop-color:#ffaa00;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop3381"
|
||||
style="stop-color:#faff2b;stop-opacity:1"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3864-0">
|
||||
<stop
|
||||
id="stop3866-5"
|
||||
style="stop-color:#0619c0;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop3868-7"
|
||||
style="stop-color:#379cfb;stop-opacity:1"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient5048">
|
||||
<stop
|
||||
id="stop5050"
|
||||
style="stop-color:#000000;stop-opacity:0"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop5056"
|
||||
style="stop-color:#000000;stop-opacity:1"
|
||||
offset="0.5" />
|
||||
<stop
|
||||
id="stop5052"
|
||||
style="stop-color:#000000;stop-opacity:0"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3841-0-3">
|
||||
<stop
|
||||
id="stop3843-1-3"
|
||||
style="stop-color:#0619c0;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop3845-0-8"
|
||||
style="stop-color:#379cfb;stop-opacity:1"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
cx="20.892099"
|
||||
cy="114.5684"
|
||||
r="5.256"
|
||||
fx="20.892099"
|
||||
fy="114.5684"
|
||||
id="aigrd2"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
id="stop15566"
|
||||
style="stop-color:#f0f0f0;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop15568"
|
||||
style="stop-color:#9a9a9a;stop-opacity:1"
|
||||
offset="1" />
|
||||
</radialGradient>
|
||||
<radialGradient
|
||||
cx="20.892099"
|
||||
cy="64.567902"
|
||||
r="5.257"
|
||||
fx="20.892099"
|
||||
fy="64.567902"
|
||||
id="aigrd3"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
id="stop15573"
|
||||
style="stop-color:#f0f0f0;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop15575"
|
||||
style="stop-color:#9a9a9a;stop-opacity:1"
|
||||
offset="1" />
|
||||
</radialGradient>
|
||||
<linearGradient
|
||||
id="linearGradient15662">
|
||||
<stop
|
||||
id="stop15664"
|
||||
style="stop-color:#ffffff;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop15666"
|
||||
style="stop-color:#f8f8f8;stop-opacity:1"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
cx="33.966679"
|
||||
cy="35.736916"
|
||||
r="86.70845"
|
||||
fx="33.966679"
|
||||
fy="35.736916"
|
||||
id="radialGradient4452"
|
||||
xlink:href="#linearGradient259"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.96049297,0,0,1.041132,-52.144249,-702.33158)" />
|
||||
<linearGradient
|
||||
id="linearGradient259">
|
||||
<stop
|
||||
id="stop260"
|
||||
style="stop-color:#fafafa;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop261"
|
||||
style="stop-color:#bbbbbb;stop-opacity:1"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
cx="8.824419"
|
||||
cy="3.7561285"
|
||||
r="37.751713"
|
||||
fx="8.824419"
|
||||
fy="3.7561285"
|
||||
id="radialGradient4454"
|
||||
xlink:href="#linearGradient269"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.96827297,0,0,1.032767,-48.790699,-701.68513)" />
|
||||
<linearGradient
|
||||
id="linearGradient269">
|
||||
<stop
|
||||
id="stop270"
|
||||
style="stop-color:#a3a3a3;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop271"
|
||||
style="stop-color:#4c4c4c;stop-opacity:1"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4095">
|
||||
<stop
|
||||
id="stop4097"
|
||||
style="stop-color:#005bff;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop4099"
|
||||
style="stop-color:#c1e3f7;stop-opacity:1"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
x1="394.15784"
|
||||
y1="185.1304"
|
||||
x2="434.73947"
|
||||
y2="140.22731"
|
||||
id="linearGradient4253"
|
||||
xlink:href="#linearGradient4247"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.94231826,0,0,0.94231826,23.727549,8.8262536)" />
|
||||
<linearGradient
|
||||
id="linearGradient4247">
|
||||
<stop
|
||||
id="stop4249"
|
||||
style="stop-color:#2e8207;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop4251"
|
||||
style="stop-color:#52ff00;stop-opacity:1"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
cx="225.26402"
|
||||
cy="672.79736"
|
||||
r="34.345188"
|
||||
fx="225.26402"
|
||||
fy="672.79736"
|
||||
id="radialGradient4317"
|
||||
xlink:href="#linearGradient3144-8"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1,0,0,0.6985294,0,202.82863)" />
|
||||
<linearGradient
|
||||
id="linearGradient3144-8">
|
||||
<stop
|
||||
id="stop3146-96"
|
||||
style="stop-color:#ffffff;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop3148-4"
|
||||
style="stop-color:#ffffff;stop-opacity:0"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<metadata
|
||||
id="metadata3617">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1">
|
||||
<path
|
||||
d="M 7.090909,5.8181818 C 15.272728,20 -3.7471829,48.338335 31.636364,48.363637 61.272846,26.482175 48.000001,19.757576 56.181819,5.4545454 l 0,0"
|
||||
id="path3179"
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
|
||||
<path
|
||||
d="M 6,48 31.560197,48.181818 61.382433,24.261076"
|
||||
id="path3082"
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<g
|
||||
transform="matrix(-0.11387155,-0.09751677,0.09751677,-0.11387155,-9.9749576,141.51281)"
|
||||
id="g4248">
|
||||
<path
|
||||
d="m 245.71428,655.2193 a 48.57143,48.57143 0 1 1 -97.14286,0 48.57143,48.57143 0 1 1 97.14286,0 z"
|
||||
id="path4250"
|
||||
style="fill:#0048ff;fill-opacity:1;stroke:#000000;stroke-width:5.80000019;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
|
||||
<path
|
||||
d="m 259.60921,672.79736 a 34.34519,23.991124 0 1 1 -68.69038,0 34.34519,23.991124 0 1 1 68.69038,0 z"
|
||||
transform="matrix(0.8513023,-0.5246754,0.5246754,0.8513023,-338.69692,214.19328)"
|
||||
id="path4252"
|
||||
style="fill:url(#radialGradient4317);fill-opacity:1;stroke:none" />
|
||||
</g>
|
||||
<path
|
||||
d="m -28.545455,43.545456 a 1.727273,1.727273 0 1 1 -3.454546,0 1.727273,1.727273 0 1 1 3.454546,0 z"
|
||||
transform="translate(36.727273,4.3636364)"
|
||||
id="path3084"
|
||||
style="color:#000000;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
d="m 62.574703,24.99591 a 1.727273,1.727273 0 0 1 -3.454546,0 1.727273,1.727273 0 1 1 3.454546,0 z"
|
||||
id="path3084-5"
|
||||
style="color:#000000;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 9.5 KiB |
Loading…
Reference in New Issue
Block a user