This is an Inkscape extension that clones an object. It makes multiple clones that shrink toward a vanishing point, necessary for a perspective drawing.
This is an Inkscape extension that clones an object. It makes multiple clones that shrink toward a vanishing point, necessary for a perspective drawing.
Inkscape is Free and Open Source Software licensed under the GPL.
With thanks to: Fastly OSUOSL Sponsors The Authors
Hello,
Thank you for providing this extension for Inkscape users!
This is just to let you know that most 3rd party Inkscape extensions, like this one, probably will not work with the upcoming new Inkscape version, the long-awaited version 1.0.
Here is the info you need to update this extension, so that it will work with 1.0 and future versions.
https://wiki.inkscape.org/wiki/index.php?title=Updating_your_Extension_for_1.0
If you have further questions, you can contact Inkscape developers via mailing lists (https://lists.inkscape.org/postorius/lists/?all-lists), forum (https://inkscape.org/forums/extensions/), or the chatroom (https://chat.inkscape.org/channel/team_devel)
If you have already updated it, please disregard this message.
All best,
brynn
For inkscape 1.0 the updated code is
#!/usr/bin/env python3
import sys
import math
import inkex
import simpletransform
from lxml import etree
class clonesPerspectiveEffect(inkex.Effect):
def __init__(self):
inkex.Effect.__init__(self)
self.arg_parser.add_argument('--num', type = int, default = 5, help = 'Drag out center of rotation before calling')
self.arg_parser.add_argument('--ratio', type = float, default = 0.9, help = 'Ratio of size of nearest neighbor to first. Must be < 1')
def effect(self):
global boxstring
global seld
svg = self.document.getroot()
num = int( self.options.num )
ratio = float( self.options.ratio)
seld = self.svg.selected
if 1 != len(seld) :
inkex.errormsg("Select exactly 1 thing. Group if necessary")
sys.exit(1)
id = list(seld.keys())[0]
sel = seld[id]
dic = sel.attrib
try :
tx = dic[inkex.addNS('transform-center-x','inkscape') ]
except KeyError :
tx = '0.'
try :
ty = dic[inkex.addNS('transform-center-y','inkscape') ]
except KeyError :
ty = '0.'
if float(tx) == 0. and float(ty) == 0. :
inkex.errormsg("Center of rotation at center of object")
sys.exit(1)
for node in sel:
width = node.bounding_box().right - node.bounding_box().left
height = node.bounding_box().bottom - node.bounding_box().top
cx = float(node.bounding_box().left) + 0.5 * width #Find center of selected object
cy = float(node.bounding_box().top) + 0.5 * height #Find center of selected object
tx = float(tx)
ty = float(ty)
crat = 1.0
otx = tx
oty = ty
parent = sel.getparent()
j = parent.index(sel)
for i in range(num) :
crat *= ratio
tx *= ratio
ty *= ratio
att = {
"id" : self.svg.get_unique_id("clone" + id),
inkex.addNS('href','xlink') : "#" + id,
inkex.addNS('transform-center-x','inkscape') : str(tx),
inkex.addNS('transform-center-y','inkscape') : str(ty),
# "x" : "0",
# "y" : "0",
'transform' : ("matrix(%f,0,0,%f,%f,%f)" %
(crat, crat,(1. - crat)*(cx + otx),
(1. - crat)*(cy - oty))),
#WHY Inkscape and SVG run +y in OPPOSITE directions is BEYOND me.
"width" : "100%",
"height" : "100%",
}
parent.insert(j, etree.Element('use', att) )
# Create effect instance and apply it.
clonesPerspectiveEffect().run()
sys.exit(0)
for inkscape 1.1 it has to be changed another times
for InkScape 1.1dev this does work:
#!/usr/bin/env python3
import sys
import math
import inkex
import simpletransform
from lxml import etree
class clonesPerspectiveEffect(inkex.Effect):
def __init__(self):
inkex.Effect.__init__(self)
self.arg_parser.add_argument('--num', type = int, default = 5, help = 'Drag out center of rotation before calling')
self.arg_parser.add_argument('--ratio', type = float, default = 0.9, help = 'Ratio of size of nearest neighbor to first. Must be < 1')
def effect(self):
svg = self.document.getroot()
num = int( self.options.num )
ratio = float( self.options.ratio)
if 1 != len(self.svg.selected) :
inkex.errormsg("Select exactly 1 thing. Group if necessary")
sys.exit(1)
id = self.svg.selected[0].get('id')
sel = self.svg.selected[id]
dic = sel.attrib
try :
tx = dic[inkex.addNS('transform-center-x','inkscape') ]
except KeyError :
tx = '0.'
try :
ty = dic[inkex.addNS('transform-center-y','inkscape') ]
except KeyError :
ty = '0.'
if float(tx) == 0. and float(ty) == 0. :
inkex.errormsg("Center of rotation at center of object")
sys.exit(1)
for node in sel:
width = node.bounding_box().right - node.bounding_box().left
height = node.bounding_box().bottom - node.bounding_box().top
cx = float(node.bounding_box().left) + 0.5 * width #Find center of selected object
cy = float(node.bounding_box().top) + 0.5 * height #Find center of selected object
tx = float(tx)
ty = float(ty)
crat = 1.0
otx = tx
oty = ty
parent = sel.getparent()
j = parent.index(sel)
for i in range(num) :
crat *= ratio
tx *= ratio
ty *= ratio
att = {
"id" : self.svg.get_unique_id("clone" + id),
inkex.addNS('href','xlink') : "#" + id,
inkex.addNS('transform-center-x','inkscape') : str(tx),
inkex.addNS('transform-center-y','inkscape') : str(ty),
# "x" : "0",
# "y" : "0",
'transform' : ("matrix(%f,0,0,%f,%f,%f)" %
(crat, crat,(1. - crat)*(cx + otx),
(1. - crat)*(cy - oty))),
#WHY Inkscape and SVG run +y in OPPOSITE directions is BEYOND me.
"width" : "100%",
"height" : "100%",
}
parent.insert(j, etree.Element('use', att) )
# Create effect instance and apply it.
clonesPerspectiveEffect().run()