removed "Ofsplot" and "boundingbox" due to unresolved license status, re-added "netting" and "scatter"
This commit is contained in:
parent
3f8da06b73
commit
bfe8c6b7a6
5
extensions/desktop.ini
Normal file
5
extensions/desktop.ini
Normal file
@ -0,0 +1,5 @@
|
||||
[LocalizedFileNames]
|
||||
fablabchemnitz_scatter.inx=@fablabchemnitz_scatter.inx,0
|
||||
fablabchemnitz_scatter.py=@fablabchemnitz_scatter.py,0
|
||||
fablabchemnitz_netting.inx=@fablabchemnitz_netting.inx,0
|
||||
fablabchemnitz_netting.py=@fablabchemnitz_netting.py,0
|
@ -1,58 +0,0 @@
|
||||
#!/usr/bin/env python2
|
||||
|
||||
import sys
|
||||
sys.path.append('/usr/share/inkscape/extensions')
|
||||
|
||||
from collections import defaultdict
|
||||
|
||||
from inkex import Effect as InkscapeEffect
|
||||
from inkex import etree, addNS
|
||||
|
||||
from simpletransform import computeBBox, applyTransformToNode
|
||||
from simplestyle import formatStyle
|
||||
from simplepath import parsePath, translatePath, formatPath
|
||||
|
||||
class DrawBBoxes(InkscapeEffect):
|
||||
def __init__(self):
|
||||
InkscapeEffect.__init__(self)
|
||||
self.filename = sys.argv[-1]
|
||||
|
||||
def effect(self):
|
||||
if len(self.selected) > 0:
|
||||
bboxes = self.calculate_bboxes(self.selected)
|
||||
for id, node, bbox in bboxes:
|
||||
self.draw_bbox(bbox)
|
||||
|
||||
def calculate_bboxes(self, nodes):
|
||||
bboxes = [(id, node, computeBBox([node]))
|
||||
for id, node in nodes.items()]
|
||||
|
||||
return bboxes
|
||||
|
||||
def draw_bbox(self, bbox):
|
||||
(x1, x2, y1, y2) = bbox
|
||||
width = x2 - x1
|
||||
height = y2 - y1
|
||||
self.draw_rect(x1, y1, width, height)
|
||||
|
||||
#SVG element generation routine
|
||||
def draw_rect(self, x, y, width, height):
|
||||
layer = self.current_layer
|
||||
|
||||
style = { 'stroke' : '#ff0000',
|
||||
'stroke-width' : '1',
|
||||
'fill' : 'none',
|
||||
}
|
||||
|
||||
attribs = {
|
||||
'style' : formatStyle(style),
|
||||
'x' : str(x),
|
||||
'y' : str(y),
|
||||
'width' : str(width),
|
||||
'height' : str(height),
|
||||
}
|
||||
|
||||
rect = etree.SubElement(layer, addNS('rect','svg'), attribs )
|
||||
|
||||
effect = DrawBBoxes()
|
||||
effect.affect()
|
@ -1,12 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||
<_name>Bounding Box</_name>
|
||||
<id>fablabchemnitz.de.boundingbox</id>
|
||||
<_name>Netting</_name>
|
||||
<id>fablabchemnitz.de.netting</id>
|
||||
<dependency type="executable" location="extensions">fablabchemnitz_netting.py</dependency>
|
||||
<dependency type="executable" location="extensions">inkex.py</dependency>
|
||||
<dependency type="executable" location="extensions">fablabchemnitz_boundingbox.py</dependency>
|
||||
<param name="help_text" type="description">Draws bounding boxes around selected objects, useful for debugging. Author: Pawel Mosakowski</param>
|
||||
<_param name="title" type="description">This effect net in the a path alternately.</_param>
|
||||
<param name="s_width" type="float" _gui-text="Stroke Width, px">1.0</param>
|
||||
<effect>
|
||||
<object-type>all</object-type>
|
||||
<object-type>path</object-type>
|
||||
<effects-menu>
|
||||
<submenu _name="FabLab Chemnitz">
|
||||
<submenu _name="Shape/Pattern from existing Path(s)" />
|
||||
@ -14,6 +15,6 @@
|
||||
</effects-menu>
|
||||
</effect>
|
||||
<script>
|
||||
<command reldir="extensions" interpreter="python">fablabchemnitz_boundingbox.py</command>
|
||||
<command reldir="extensions" interpreter="python">fablabchemnitz_netting.py</command>
|
||||
</script>
|
||||
</inkscape-extension>
|
63
extensions/fablabchemnitz_netting.py
Normal file
63
extensions/fablabchemnitz_netting.py
Normal file
@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env python
|
||||
'''
|
||||
netting.py
|
||||
Sunabe kazumichi 2010/3/4
|
||||
http://dp48069596.lolipop.jp/
|
||||
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU 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 program nets in the line.
|
||||
'''
|
||||
import random, math, inkex, simplestyle, cubicsuperpath
|
||||
|
||||
|
||||
class RadiusRandomize(inkex.Effect):
|
||||
def __init__(self):
|
||||
inkex.Effect.__init__(self)
|
||||
self.OptionParser.add_option("-w", "--s_width",
|
||||
action="store", type="float",
|
||||
dest="s_width", default=1.0,
|
||||
help="atrke width")
|
||||
self.OptionParser.add_option("--title")
|
||||
|
||||
def effect(self):
|
||||
path_strings = []
|
||||
net_strings= ["M"]
|
||||
my_path = inkex.etree.Element(inkex.addNS('path','svg'))
|
||||
s = {'stroke-width': self.options.s_width, 'stroke': '#000000', 'fill': 'none' }
|
||||
my_path.set('style', simplestyle.formatStyle(s))
|
||||
for id, node in self.selected.iteritems():
|
||||
if node.tag == inkex.addNS('path','svg'):
|
||||
d = node.get('d')
|
||||
p = cubicsuperpath.parsePath(d)
|
||||
for subpath in p:
|
||||
for i, csp in enumerate(subpath):
|
||||
path_strings.append("%f,%f" % ( csp[1][0], csp[1][1]))
|
||||
node.set('d',cubicsuperpath.formatPath(p))
|
||||
|
||||
while len(path_strings)>0 :
|
||||
net_strings.append(path_strings.pop(0))
|
||||
if len(path_strings)>0 :
|
||||
net_strings.append(path_strings.pop())
|
||||
my_path.set('d', " ".join(net_strings))
|
||||
self.current_layer.append( my_path )
|
||||
|
||||
|
||||
|
||||
|
||||
e = RadiusRandomize()
|
||||
e.affect()
|
||||
|
@ -1,23 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||
<_name>Ofsplot (Offset Paths)</_name>
|
||||
<id>fablabchemnitz.de.ofsplot</id>
|
||||
<dependency type="executable" location="extensions">fablabchemnitz_ofsplot.py</dependency>
|
||||
<param name="count" type="int" min="0" max="100000" _gui-text="Number of offset paths:">10</param>
|
||||
<param name="ofs" type="float" min="-1000" max="+1000" _gui-text="Offset between two paths:">0.8</param>
|
||||
<param name="init_ofs" type="float" min="-1000" max="+1000" _gui-text="Initial offset from original path:">0.8</param>
|
||||
<param name="copy_org" type="boolean" _gui-text="Copy original path (=keep it)">0</param>
|
||||
<param name="ofs_incr" type="float" min="-1000" max="+1000" _gui-text="Offset increase per iteration:">0.8</param>
|
||||
<_param name="settingsHelp" type="description">Python library pyclipper needs to be installed. Use Flatten Bezier plugin in advance of this plugin.</_param>
|
||||
<effect>
|
||||
<object-type>all</object-type>
|
||||
<effects-menu>
|
||||
<submenu _name="FabLab Chemnitz">
|
||||
<submenu _name="Shape/Pattern from existing Path(s)"/>
|
||||
</submenu>
|
||||
</effects-menu>
|
||||
</effect>
|
||||
<script>
|
||||
<command reldir="extensions" interpreter="python">fablabchemnitz_ofsplot.py</command>
|
||||
</script>
|
||||
</inkscape-extension>
|
@ -1,111 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
from __future__ import print_function
|
||||
|
||||
import inkex
|
||||
import cubicsuperpath, simplestyle, copy, math, re, bezmisc, simplepath
|
||||
import pyclipper
|
||||
import sys
|
||||
|
||||
def eprint(*args, **kwargs):
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
|
||||
|
||||
class ofsplot(inkex.Effect):
|
||||
def __init__(self):
|
||||
inkex.Effect.__init__(self)
|
||||
self.OptionParser.add_option("--count",
|
||||
action="store", type="int",
|
||||
dest="count", default=10,
|
||||
help="Number of offset operations")
|
||||
self.OptionParser.add_option("--ofs",
|
||||
action="store", type="float",
|
||||
dest="offset", default=2,
|
||||
help="Offset amount")
|
||||
self.OptionParser.add_option("--init_ofs",
|
||||
action="store", type="float",
|
||||
dest="init_offset", default=2,
|
||||
help="Initial Offset Amount")
|
||||
self.OptionParser.add_option("--copy_org",
|
||||
action="store", type="inkbool",
|
||||
dest="copy_org", default=True,
|
||||
help="copy original path")
|
||||
self.OptionParser.add_option("--ofs_incr",
|
||||
action="store", type="float",
|
||||
dest="offset_increase", default=2,
|
||||
help="Offset increase between iterations")
|
||||
|
||||
|
||||
|
||||
|
||||
def effect(self):
|
||||
|
||||
for id, node in self.selected.iteritems():
|
||||
if node.tag == inkex.addNS('path','svg'):
|
||||
p = cubicsuperpath.parsePath(node.get('d'))
|
||||
|
||||
scale_factor=5.0
|
||||
|
||||
|
||||
pco = pyclipper.PyclipperOffset()
|
||||
|
||||
new = []
|
||||
|
||||
|
||||
# load in initial paths
|
||||
for sub in p:
|
||||
sub_simple = []
|
||||
h1_simple = []
|
||||
h2_simple = []
|
||||
for item in sub:
|
||||
itemx = [float(z)*scale_factor for z in item[1]]
|
||||
sub_simple.append(itemx)
|
||||
#eprint(itemx)
|
||||
#h1_simple.append(item[0]-item[1]) # handle 1 offset
|
||||
#h2_simple.append(item[2]-item[1]) # handle 2 offset
|
||||
|
||||
pco.AddPath(sub_simple, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON)
|
||||
|
||||
|
||||
|
||||
# calculate offset paths for different offset amounts
|
||||
offset_list = []
|
||||
offset_list.append(self.options.init_offset)
|
||||
for i in range(0,self.options.count+1):
|
||||
ofs_inc = +math.pow(float(i)*self.options.offset_increase,2)
|
||||
if self.options.offset_increase <0:
|
||||
ofs_inc = -ofs_inc
|
||||
offset_list.append(offset_list[0]+float(i)*self.options.offset+ofs_inc)
|
||||
|
||||
|
||||
solutions = []
|
||||
for offset in offset_list:
|
||||
solution = pco.Execute(offset*scale_factor)
|
||||
solutions.append(solution)
|
||||
if len(solution)<=0:
|
||||
continue # no more loops to go, will provide no results.
|
||||
|
||||
|
||||
# re-arrange solutions to fit expected format & add to array
|
||||
for solution in solutions:
|
||||
for sol in solution:
|
||||
solx = [[float(s[0])/scale_factor, float(s[1])/scale_factor] for s in sol]
|
||||
sol_p = [[a,a,a] for a in solx]
|
||||
sol_p.append(sol_p[0][:])
|
||||
new.append(sol_p)
|
||||
|
||||
|
||||
|
||||
|
||||
# add old, just to keep (make optional!)
|
||||
if self.options.copy_org:
|
||||
for sub in p:
|
||||
new.append(sub)
|
||||
|
||||
node.set('d',cubicsuperpath.formatPath(new))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
e = ofsplot()
|
||||
e.affect()
|
||||
|
24
extensions/fablabchemnitz_scatter.inx
Normal file
24
extensions/fablabchemnitz_scatter.inx
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||
<_name>Scatter 2</_name>
|
||||
<id>fablabchemnitz.de.scatter2</id>
|
||||
<dependency type="executable" location="extensions">pathmodifier.py</dependency>
|
||||
<dependency type="executable" location="extensions">fablabchemnitz_scatter.py</dependency>
|
||||
<dependency type="executable" location="extensions">inkex.py</dependency>
|
||||
<param name="title" type="description">This effect scatters pattern objects randomly around segment points of arbitrary "skeleton" paths. The pattern is the top most object in the selection. Random_off:density=1,offset=0</param>
|
||||
<param name="random" type="boolean" _gui-text="Random : off : density=1 offset=0">true</param>
|
||||
<param name="density" type="float" _gui-text="Density : random only" min="1" max="100">6</param>
|
||||
<param name="offset" type="float" _gui-text="Offset : random: offset area px" min="0" max="1000">3</param>
|
||||
<param name="scale" type="float" _gui-text="Scale : random:from value to 100%" min="1" max="100">20.0</param>
|
||||
<param name="rotation" type="float" _gui-text="Rotation : random: from -30 to 30 dgree" min="-30" max="30">20.0</param>
|
||||
<effect>
|
||||
<effects-menu>
|
||||
<submenu _name="FabLab Chemnitz">
|
||||
<submenu _name="Shape/Pattern from existing Path(s)"/>
|
||||
</submenu>
|
||||
</effects-menu>
|
||||
</effect>
|
||||
<script>
|
||||
<command reldir="extensions" interpreter="python">fablabchemnitz_scatter.py</command>
|
||||
</script>
|
||||
</inkscape-extension>
|
140
extensions/fablabchemnitz_scatter.py
Normal file
140
extensions/fablabchemnitz_scatter.py
Normal file
@ -0,0 +1,140 @@
|
||||
#!/usr/bin/env python
|
||||
'''
|
||||
scatter.py
|
||||
Sunabe kazumichi 2009/9/29
|
||||
http://dp48069596.lolipop.jp/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU 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
|
||||
|
||||
|
||||
attention:when rotation degree become large, patterns are deformed largely.
|
||||
therefore,restricted the rotation in range -30<deg<30.
|
||||
|
||||
'''
|
||||
import inkex, cubicsuperpath, bezmisc
|
||||
import pathmodifier,simpletransform
|
||||
import copy, math, re, random
|
||||
|
||||
def translate(pathcomp,dx,dy):
|
||||
for ctl in pathcomp:
|
||||
for pt in ctl:
|
||||
pt[0]+=dx
|
||||
pt[1]+=dy
|
||||
|
||||
def scale(pathcomp,scale,org):
|
||||
for ctl in pathcomp:
|
||||
for pt in ctl:
|
||||
pt[0]=org[0]+(pt[0]-org[0])*scale
|
||||
pt[1]=org[1]+(pt[1]-org[1])*scale
|
||||
|
||||
def rotate(pathcomp,angle):
|
||||
for ctl in pathcomp:
|
||||
for pt in ctl:
|
||||
pt[0]=pt[0]*math.cos(angle)-pt[1]*math.sin(angle)
|
||||
pt[1]=pt[0]*math.sin(angle)+pt[1]*math.cos(angle)
|
||||
|
||||
class ScatterAlongPath(pathmodifier.Diffeo):
|
||||
def __init__(self):
|
||||
pathmodifier.Diffeo.__init__(self)
|
||||
self.OptionParser.add_option("--title")
|
||||
self.OptionParser.add_option("-r", "--random",
|
||||
action="store", type="inkbool",
|
||||
dest="random", default=True,
|
||||
help="random pattern on the skeleton")
|
||||
self.OptionParser.add_option("-d", "--density",
|
||||
action="store", type="int",
|
||||
dest="density", default=3)
|
||||
self.OptionParser.add_option("-o", "--offset",
|
||||
action="store", type="float",
|
||||
dest="offset", default=0.0, help="offset")
|
||||
self.OptionParser.add_option("-s", "--scale",
|
||||
action="store", type="float",
|
||||
dest="scale", default=100, help="scale")
|
||||
self.OptionParser.add_option("-p", "--rotation",
|
||||
action="store", type="float",
|
||||
dest="rotation", default=0,
|
||||
help="rotation pattern on the skeleton")
|
||||
|
||||
def prepareSelectionList(self):
|
||||
idList=self.options.ids
|
||||
idList=pathmodifier.zSort(self.document.getroot(),idList)
|
||||
id = idList[-1]
|
||||
self.patterns={id:self.selected[id]}
|
||||
self.patterns=self.duplicateNodes(self.patterns)
|
||||
self.expandGroupsUnlinkClones(self.patterns, True, True)
|
||||
self.objectsToPaths(self.patterns)
|
||||
del self.selected[id]
|
||||
self.skeletons=self.selected
|
||||
self.expandGroupsUnlinkClones(self.skeletons, True, False)
|
||||
self.objectsToPaths(self.skeletons)
|
||||
|
||||
def effect(self):
|
||||
if len(self.options.ids)<2:
|
||||
inkex.debug("This extension requires that you select two paths.")
|
||||
return
|
||||
self.prepareSelectionList()
|
||||
bbox=simpletransform.computeBBox(self.patterns.values())
|
||||
for id, node in self.patterns.iteritems():
|
||||
if node.tag == inkex.addNS('path','svg') or node.tag=='path':
|
||||
d = node.get('d')
|
||||
p0 = cubicsuperpath.parsePath(d)
|
||||
newp=[]
|
||||
for skelnode in self.skeletons.itervalues():
|
||||
self.curSekeleton=cubicsuperpath.parsePath(skelnode.get('d'))
|
||||
den=1
|
||||
while den <= self.options.density:
|
||||
for comp in self.curSekeleton:
|
||||
p=copy.deepcopy(p0)
|
||||
if self.options.random:
|
||||
xoffset=-bbox[0]-(bbox[1]-bbox[0])/2+random.uniform(-self.options.offset, self.options.offset)
|
||||
yoffset=-(bbox[2]+bbox[3])/2-random.uniform(-self.options.offset, self.options.offset)
|
||||
else:
|
||||
self.options.density=1
|
||||
self.options.offset=0
|
||||
xoffset=-bbox[0]-(bbox[1]-bbox[0])/2+self.options.offset
|
||||
yoffset=-(bbox[2]+bbox[3])/2-self.options.offset
|
||||
|
||||
NbCopies=len(comp)
|
||||
new=[]
|
||||
for sub in p:
|
||||
for i in range(0,NbCopies,1):
|
||||
new.append(copy.deepcopy(sub))
|
||||
p=new
|
||||
for sub in p:
|
||||
translate(sub,xoffset,yoffset)
|
||||
for sub in p:
|
||||
if self.options.random:
|
||||
scale(sub,random.uniform(self.options.scale, 100)/100,(0,0))
|
||||
else:
|
||||
scale(sub,self.options.scale/100,(0,0))
|
||||
for sub in p:
|
||||
if self.options.random:
|
||||
rotate(sub,random.uniform(-self.options.rotation*math.pi/180, self.options.rotation*math.pi/180))
|
||||
else:
|
||||
rotate(sub,self.options.rotation*math.pi/180)
|
||||
for i,sub in enumerate(p):
|
||||
try:
|
||||
translate(sub,comp[i][1][0],comp[i][1][1])
|
||||
except:
|
||||
pass
|
||||
newp+=p
|
||||
den+=1
|
||||
|
||||
|
||||
node.set('d', cubicsuperpath.formatPath(newp))
|
||||
e = ScatterAlongPath()
|
||||
e.affect()
|
||||
|
||||
|
Reference in New Issue
Block a user