Upgraded Create Links extension - first well working version
This commit is contained in:
parent
be4b28db3b
commit
67859849e9
@ -4,19 +4,6 @@
|
|||||||
<id>fablabchemnitz.de.create_links</id>
|
<id>fablabchemnitz.de.create_links</id>
|
||||||
<param name="main_tabs" type="notebook">
|
<param name="main_tabs" type="notebook">
|
||||||
<page name="settings" gui-text="Settings">
|
<page name="settings" gui-text="Settings">
|
||||||
<label appearance="header">Link Parameters</label>
|
|
||||||
<param name="length_link" type="float" min="0.000" max="9999.000" precision="3" gui-text="Link length">1.000</param>
|
|
||||||
<param name="length_stroke" type="float" min="0.000" max="9999.000" precision="3" gui-text="Stroke length">0.000</param>
|
|
||||||
<param name="length_between_strokes" type="float" min="0.000" max="9999.000" precision="3" gui-text="Length between strokes">0.000</param>
|
|
||||||
<spacer/>
|
|
||||||
<label appearance="header">Automatic Placement</label>
|
|
||||||
<param name="length_filter" type="bool" gui-text="Enable path length filtering">false</param>
|
|
||||||
<param name="length_filter_value" type="float" min="0.000" max="9999.000" precision="3" gui-text="Paths with length more than">0.000</param>
|
|
||||||
<param name="link_count" type="int" min="0" max="9999" gui-text="Link count">1</param>
|
|
||||||
<param name="length_between_links" type="float" min="0.000" max="9999.000" precision="3" gui-text="Length between links">100.000</param>
|
|
||||||
<separator/>
|
|
||||||
<param name="link_offset" type="float" min="0.000" max="9999.000" precision="3" gui-text="Link offset">0.000</param>
|
|
||||||
<param name="keep_selected" type="bool" gui-text="Keep selected elements">false</param>
|
|
||||||
<param name="unit" type="optiongroup" appearance="combo" gui-text="Units">
|
<param name="unit" type="optiongroup" appearance="combo" gui-text="Units">
|
||||||
<option value="mm">mm</option>
|
<option value="mm">mm</option>
|
||||||
<option value="cm">cm</option>
|
<option value="cm">cm</option>
|
||||||
@ -26,13 +13,24 @@
|
|||||||
<option value="pc">pc</option>
|
<option value="pc">pc</option>
|
||||||
<option value="percent">%</option>
|
<option value="percent">%</option>
|
||||||
</param>
|
</param>
|
||||||
|
<param name="link_count" type="int" min="1" max="9999" gui-text="Link count">1</param>
|
||||||
|
<param name="link_multiplicator (experimental)" type="int" min="0" max="9999" gui-text="Link multiplicator" gui-description="If se, we create a set of multiple gaps of same size next to the main gap">0</param>
|
||||||
|
<param name="length_link" type="float" min="0.000" max="9999.000" precision="3" gui-text="Link length (the length of the gap)">1.000</param>
|
||||||
|
<param name="link_offset" type="float" min="-9999.000.000" max="9999.000" precision="3" gui-text="Link offset (+/-)">0.000</param>
|
||||||
|
<param name="length_filter" type="bool" gui-text="Enable path length filtering">false</param>
|
||||||
|
<param name="length_filter_value" type="float" min="0.000" max="9999.000" precision="3" gui-text="Paths with length more than">0.000</param>
|
||||||
|
<param name="custom_dasharray" type="bool" gui-text="Enable custom dash pattern">false</param>
|
||||||
|
<param name="custom_dasharray_value" type="string" gui-text="Dash pattern" gui-description="A list of separated lengths that specify the lengths of alternating dashes and gaps. Input only accepts numbers. It ignores percentages or other characters.">10 5</param>
|
||||||
|
<param name="keep_selected" type="bool" gui-text="Keep selected elements">false</param>
|
||||||
|
<param name="breakapart" type="bool" gui-text="Break apart" gui-description="Performs CTRL + SHIFT + K to break a combined path into it's parts">false</param>
|
||||||
|
<param name="show_info" type="bool" gui-text="Print some length and pattern information" gui-description="Warning: might freeze InkScape forever if you have a lot of nodes because we create too much print output. Use for debugging only!">false</param>
|
||||||
</page>
|
</page>
|
||||||
<page name="about" gui-text="About">
|
<page name="about" gui-text="About">
|
||||||
<label appearance="header">Create Links</label>
|
<label appearance="header">Create Links</label>
|
||||||
<label>Stadtfabrikanten e.V. (2021)</label>
|
<label>Stadtfabrikanten e.V. (2021)</label>
|
||||||
<spacer/>
|
<spacer/>
|
||||||
<label>This piece of software is part of the MightyScape for InkScape 1.0/1.1dev Extension Collection</label>
|
<label>This piece of software is part of the MightyScape for InkScape 1.0/1.1dev Extension Collection.</label>
|
||||||
<label>you found a bug or got some fresh code? Just report to mario.voigt@stadtfabrikanten.org. Thanks!</label>
|
<label>You found a bug or got some fresh code? Just report to mario.voigt@stadtfabrikanten.org. Thanks!</label>
|
||||||
<label appearance="url">https://fablabchemnitz.de</label>
|
<label appearance="url">https://fablabchemnitz.de</label>
|
||||||
<label>License: GNU GPL v3</label>
|
<label>License: GNU GPL v3</label>
|
||||||
</page>
|
</page>
|
||||||
|
@ -25,28 +25,60 @@ It is a modification of the file convert2dash.py
|
|||||||
Extension to convert paths into dash-array line
|
Extension to convert paths into dash-array line
|
||||||
|
|
||||||
"""
|
"""
|
||||||
import inkex
|
|
||||||
from inkex import bezier, CubicSuperPath, Group, PathElement
|
|
||||||
from inkex.bezier import csplength
|
|
||||||
import copy
|
import copy
|
||||||
|
import re
|
||||||
|
|
||||||
|
import inkex
|
||||||
|
from inkex import bezier, Path, CubicSuperPath, Group, PathElement
|
||||||
|
from inkex.bezier import csplength
|
||||||
|
|
||||||
|
|
||||||
class LinksCreator(inkex.EffectExtension):
|
class LinksCreator(inkex.EffectExtension):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(LinksCreator, self).__init__()
|
super(LinksCreator, self).__init__()
|
||||||
self.arg_parser.add_argument("--main_tabs")
|
self.arg_parser.add_argument("--main_tabs")
|
||||||
|
self.arg_parser.add_argument("--unit", default="mm", help="Units")
|
||||||
|
self.arg_parser.add_argument("--link_count", type=int, default=1, help="Link count")
|
||||||
|
self.arg_parser.add_argument("--link_multiplicator", type=int, default=1, help="If se, we create a set of multiple gaps of same size next to the main gap")
|
||||||
self.arg_parser.add_argument("--length_link", type=float, default=1.000, help="Link length")
|
self.arg_parser.add_argument("--length_link", type=float, default=1.000, help="Link length")
|
||||||
self.arg_parser.add_argument("--length_stroke", type=float, default=0.000, help="Stroke length")
|
self.arg_parser.add_argument("--link_offset", type=float, default=0.000, help="Link offset (+/-)")
|
||||||
self.arg_parser.add_argument("--length_between_strokes", type=float, default=0.000, help="Length between strokes")
|
|
||||||
self.arg_parser.add_argument("--length_filter", type=inkex.Boolean, default=False, help="Enable path length filtering")
|
self.arg_parser.add_argument("--length_filter", type=inkex.Boolean, default=False, help="Enable path length filtering")
|
||||||
self.arg_parser.add_argument("--length_filter_value", type=float, default=0.000, help="Paths with length more than")
|
self.arg_parser.add_argument("--length_filter_value", type=float, default=0.000, help="Paths with length more than")
|
||||||
self.arg_parser.add_argument("--link_count", type=int, default=1, help="Link count")
|
self.arg_parser.add_argument("--custom_dasharray", type=inkex.Boolean, default=False, help="Enable custom dash pattern")
|
||||||
self.arg_parser.add_argument("--length_between_links", type=float, default=100.000, help="Length between links")
|
self.arg_parser.add_argument("--custom_dasharray_value", default="", help="A list of separated lengths that specify the lengths of alternating dashes and gaps. Input only accepts numbers. It ignores percentages or other characters.")
|
||||||
|
|
||||||
self.arg_parser.add_argument("--link_offset", type=float, default=0.000, help="Link offset")
|
|
||||||
self.arg_parser.add_argument("--keep_selected", type=inkex.Boolean, default=False, help="Keep selected elements")
|
self.arg_parser.add_argument("--keep_selected", type=inkex.Boolean, default=False, help="Keep selected elements")
|
||||||
self.arg_parser.add_argument("--unit", default="mm", help="Units")
|
self.arg_parser.add_argument("--breakapart", type=inkex.Boolean, default=False, help="Performs CTRL + SHIFT + K to break a combined path into it's parts")
|
||||||
|
self.arg_parser.add_argument("--show_info", type=inkex.Boolean, default=False, help="Print some length and pattern information")
|
||||||
|
|
||||||
|
replacedNodes = []
|
||||||
|
|
||||||
|
def breakContours(self, node): #this does the same as "CTRL + SHIFT + K"
|
||||||
|
parent = node.getparent()
|
||||||
|
idx = parent.index(node)
|
||||||
|
idSuffix = 0
|
||||||
|
raw = Path(node.get("d")).to_arrays()
|
||||||
|
subPaths, prev = [], 0
|
||||||
|
for i in range(len(raw)): # Breaks compound paths into simple paths
|
||||||
|
if raw[i][0] == 'M' and i != 0:
|
||||||
|
subPaths.append(raw[prev:i])
|
||||||
|
prev = i
|
||||||
|
subPaths.append(raw[prev:])
|
||||||
|
for subpath in subPaths:
|
||||||
|
replacedNode = copy.copy(node)
|
||||||
|
oldId = replacedNode.get('id')
|
||||||
|
|
||||||
|
replacedNode.set('d', CubicSuperPath(subpath))
|
||||||
|
replacedNode.set('id', oldId + str(idSuffix).zfill(5))
|
||||||
|
parent.insert(idx, replacedNode)
|
||||||
|
idSuffix += 1
|
||||||
|
self.replacedNodes.append(replacedNode)
|
||||||
|
parent.remove(node)
|
||||||
|
for child in node:
|
||||||
|
self.breakContours(child)
|
||||||
|
|
||||||
def effect(self):
|
def effect(self):
|
||||||
|
if len(self.svg.selected) > 0:
|
||||||
for node in self.svg.selection.filter(PathElement).values():
|
for node in self.svg.selection.filter(PathElement).values():
|
||||||
|
|
||||||
if self.options.keep_selected is True:
|
if self.options.keep_selected is True:
|
||||||
@ -58,7 +90,13 @@ class LinksCreator(inkex.EffectExtension):
|
|||||||
# we measure the length of the path to calculate the required dash configuration
|
# we measure the length of the path to calculate the required dash configuration
|
||||||
csp = node.path.transform(node.composed_transform()).to_superpath()
|
csp = node.path.transform(node.composed_transform()).to_superpath()
|
||||||
slengths, stotal = csplength(csp) #get segment lengths and total length of path in document's internal unit
|
slengths, stotal = csplength(csp) #get segment lengths and total length of path in document's internal unit
|
||||||
#inkex.utils.debug("total path length = {:1.3f} {}".format(self.svg.uutounit(stotal, self.options.unit), self.options.unit)) #show length, converted in selected unit
|
|
||||||
|
length_link = self.svg.unittouu(str(self.options.length_link) + self.options.unit)
|
||||||
|
|
||||||
|
if self.options.length_filter is True:
|
||||||
|
if stotal < self.options.length_filter_value:
|
||||||
|
inkex.utils.debug("node " + node.get('id') + " is shorter than minimum allowed length of {:1.3f}. Path length is {:1.3f}".format(self.options.length_filter_value, stotal))
|
||||||
|
break
|
||||||
|
|
||||||
'''
|
'''
|
||||||
<dasharray>
|
<dasharray>
|
||||||
@ -75,15 +113,35 @@ class LinksCreator(inkex.EffectExtension):
|
|||||||
- the array "5 14" will create 6 dashes with length = 5 and 5 gaps with length = 15 (5 + 14 + 5 + 14 + 5 + 14 + 5 + 14 + 5 + 14 + 5 = 100) - the first dash will connect to the last dash fluently
|
- the array "5 14" will create 6 dashes with length = 5 and 5 gaps with length = 15 (5 + 14 + 5 + 14 + 5 + 14 + 5 + 14 + 5 + 14 + 5 = 100) - the first dash will connect to the last dash fluently
|
||||||
in the examples above we always match the full length. But we do not always match it.
|
in the examples above we always match the full length. But we do not always match it.
|
||||||
'''
|
'''
|
||||||
#dashes = "{:1.3f} {:1.3f}".format(((stotal / self.options.link_count) - (self.options.length_link * self.options.link_count)), self.options.length_link)
|
|
||||||
dashes = []
|
dashes = []
|
||||||
dashes.append((stotal / self.options.link_count) - (self.options.length_link * self.options.link_count))
|
dashes.append((stotal - length_link * self.options.link_count) / self.options.link_count)
|
||||||
dashes.append(self.options.length_link)
|
dashes.append(length_link)
|
||||||
|
|
||||||
|
for i in range(0, self.options.link_multiplicator):
|
||||||
|
dashes.append(length_link) #stroke (=gap)
|
||||||
|
dashes.append(length_link) #gap
|
||||||
|
|
||||||
|
if self.options.custom_dasharray is True:
|
||||||
|
try:
|
||||||
|
floats = [float(dash) for dash in re.findall(r"[-+]?\d*\.\d+|\d+", self.options.custom_dasharray_value)]
|
||||||
|
if len(floats) > 0:
|
||||||
|
dashes = floats #overwrite previously calculated values with custom input
|
||||||
|
else:
|
||||||
|
raise ValueError
|
||||||
|
except:
|
||||||
|
inkex.errormsg("Error in custom dasharray string (might be empty or does not contain any numbers). Using regular input instead ...")
|
||||||
|
|
||||||
stroke_dasharray = ' '.join(format(dash, "1.3f") for dash in dashes)
|
stroke_dasharray = ' '.join(format(dash, "1.3f") for dash in dashes)
|
||||||
stroke_dashoffset = 0.0
|
stroke_dashoffset = self.svg.unittouu(str(self.options.link_offset) + self.options.unit)
|
||||||
|
|
||||||
#inkex.utils.debug("dashes = {}".format(stroke_dasharray))
|
if self.options.show_info is True:
|
||||||
|
inkex.utils.debug("node " + node.get('id'))
|
||||||
|
inkex.utils.debug("total path length = {:1.3f} {}".format(self.svg.uutounit(stotal, self.options.unit), self.options.unit)) #show length, converted in selected unit
|
||||||
|
inkex.utils.debug("total gaps = {}".format(self.options.link_count))
|
||||||
|
inkex.utils.debug("(calculated) dash/gap pattern: {} ({})".format(stroke_dasharray, self.options.unit))
|
||||||
|
inkex.utils.debug("(calculated) dash offset: {:1.3f} {}".format(self.svg.uutounit(stroke_dashoffset, self.options.unit), self.options.unit))
|
||||||
|
inkex.utils.debug("----------------------------------------------------------------")
|
||||||
|
|
||||||
# check if the node has a style attribute. If not we create a blank one with a black stroke and without fill
|
# check if the node has a style attribute. If not we create a blank one with a black stroke and without fill
|
||||||
style = None
|
style = None
|
||||||
@ -152,5 +210,16 @@ class LinksCreator(inkex.EffectExtension):
|
|||||||
node.path = CubicSuperPath(new)
|
node.path = CubicSuperPath(new)
|
||||||
node.style = style
|
node.style = style
|
||||||
|
|
||||||
|
if self.options.breakapart is True:
|
||||||
|
self.breakContours(node)
|
||||||
|
#update selection to split paths segments (does not work, so commented out)
|
||||||
|
#for replacedNode in self.replacedNodes:
|
||||||
|
# inkex.utils.debug(replacedNode.get('id'))
|
||||||
|
# self.svg.selection.set(replacedNode.get('id'))
|
||||||
|
|
||||||
|
else:
|
||||||
|
inkex.errormsg('Please select some objects first.')
|
||||||
|
return
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
LinksCreator().run()
|
LinksCreator().run()
|
Reference in New Issue
Block a user