fixes in tab generator

This commit is contained in:
Mario Voigt 2021-07-05 22:13:29 +02:00
parent d9922309c2
commit 8040fdaa70
2 changed files with 50 additions and 29 deletions

View File

@ -4,9 +4,10 @@
<id>fablabchemnitz.de.tab_generator</id> <id>fablabchemnitz.de.tab_generator</id>
<param name="usermenu" type="notebook"> <param name="usermenu" type="notebook">
<page name="settings" gui-text="Settings"> <page name="settings" gui-text="Settings">
<param name="tabangle" type="float" min="0.0" max="90.0" gui-text="Angle of tab edges (degrees):">45.0</param> <label appearance="header">Measures and tab generation</label>
<param name="tabheight" type="float" min="0.01" max="9999.0" gui-text="Height of tab:">0.4</param> <param name="tabangle" type="float" min="0.01" max="90.0" precision="2" gui-text="Angle of tab edges (degrees):">45.00</param>
<param name="dashlength" type="float" min="0.0" max="9999.0" gui-text="Length of dashline (zero for solid line):">0.1</param> <param name="tabheight" type="float" min="0.01" max="9999.0" precision="2" gui-text="Height of tab:">0.40</param>
<param name="dashlength" type="float" min="0.0" max="9999.0" precision="2" gui-text="Length of dash line (zero for solid line):" gui-description="If value larger than zero the line will split up into real dash lines (no cosmetic one's)">0.1</param>
<param name="tabsets" type="optiongroup" appearance="combo" gui-text="Tab placement on polygons with cutouts:"> <param name="tabsets" type="optiongroup" appearance="combo" gui-text="Tab placement on polygons with cutouts:">
<option value="outside">outside</option> <option value="outside">outside</option>
<option value="inside">inside</option> <option value="inside">inside</option>
@ -23,9 +24,11 @@
<option value="ft">ft</option> <option value="ft">ft</option>
<option value="yd">yd</option> <option value="yd">yd</option>
</param> </param>
<param name="strokewidth" min="0.0" max="10000.0" precision="3" gui-text="Stroke width (px)" type="float">1.0</param> <label appearance="header">Styles</label>
<param name="color_solid" type="color" appearance="colorbutton" gui-text="Solid line color">3419879935</param> <param name="cosmetic_dash_style" type="bool" gui-text="Cosmetic dash lines" gui-description="If entered dash line length is zero we can apply some cosmetic style only">false</param>
<param name="color_dash" type="color" appearance="colorbutton" gui-text="Dash line color">1592519679</param> <param name="color_solid" type="color" appearance="colorbutton" gui-text="Solid line color">4278190335</param>
<param name="color_dash" type="color" appearance="colorbutton" gui-text="Dash line color">65535</param>
<label appearance="header">Other settings</label>
<param name="print_debug" type="bool" gui-text="Print debug info">true</param> <param name="print_debug" type="bool" gui-text="Print debug info">true</param>
<param name="keep_original" type="bool" gui-text="Keep original elements">false</param> <param name="keep_original" type="bool" gui-text="Keep original elements">false</param>
</page> </page>

View File

@ -16,6 +16,7 @@
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# #
""" """
Given a closed path of straight lines, this program generates a paper model containing Given a closed path of straight lines, this program generates a paper model containing
tabs and score lines for each straight edge. tabs and score lines for each straight edge.
@ -75,16 +76,19 @@ class Tabgen(inkex.EffectExtension):
pars.add_argument("--tabangle", type=float, default=45.0, help="Angle of tab edges in degrees") pars.add_argument("--tabangle", type=float, default=45.0, help="Angle of tab edges in degrees")
pars.add_argument("--tabheight", type=float, default=0.4, help="Height of tab in dimensional units") pars.add_argument("--tabheight", type=float, default=0.4, help="Height of tab in dimensional units")
pars.add_argument("--dashlength", type=float, default=0.25, help="Length of dashline in dimentional units (zero for solid line)") pars.add_argument("--dashlength", type=float, default=0.25, help="Length of dashline in dimentional units (zero for solid line)")
pars.add_argument("--cosmetic_dash_style", type=inkex.Boolean, default=False, help="Cosmetic dash lines")
pars.add_argument("--tabsets", default="both", help="Tab placement on polygons with cutouts") pars.add_argument("--tabsets", default="both", help="Tab placement on polygons with cutouts")
pars.add_argument("--unit", default="in", help="Dimensional units of selected paths") pars.add_argument("--unit", default="in", help="Dimensional units of selected paths")
pars.add_argument("--strokewidth", type=float, default=1.0, help="Stroke width (px)") pars.add_argument("--color_solid", type=Color, default='4278190335', help="Solid line color")
pars.add_argument("--color_solid", type=Color, default='3419879935', help="Solid line color") pars.add_argument("--color_dash", type=Color, default='65535', help="Solid line dash")
pars.add_argument("--color_dash", type=Color, default='1592519679', help="Solid line dash")
pars.add_argument("--print_debug", type=inkex.Boolean, default=True, help="Print debug info") pars.add_argument("--print_debug", type=inkex.Boolean, default=True, help="Print debug info")
pars.add_argument("--keep_original", type=inkex.Boolean, default=False, help="Keep original elements") pars.add_argument("--keep_original", type=inkex.Boolean, default=False, help="Keep original elements")
#draw SVG line segment(s) between the given (raw) points
def drawline(self, dstr, name, parent, sstr=None): def drawline(self, dstr, name, parent, sstr=None):
'''
draw SVG line segment(s) between the given (raw) points
'''
line_style = {'stroke':'#000000','stroke-width':'1','fill':'none'} line_style = {'stroke':'#000000','stroke-width':'1','fill':'none'}
if sstr == None: if sstr == None:
stylestr = str(inkex.Style(line_style)) stylestr = str(inkex.Style(line_style))
@ -95,6 +99,7 @@ class Tabgen(inkex.EffectExtension):
el.style = sstr el.style = sstr
el.label = name el.label = name
def pathInsidePath(self, path, testpath): def pathInsidePath(self, path, testpath):
enclosed = True enclosed = True
for tp in testpath: for tp in testpath:
@ -104,6 +109,7 @@ class Tabgen(inkex.EffectExtension):
return enclosed # True if testpath is fully enclosed in path return enclosed # True if testpath is fully enclosed in path
return enclosed return enclosed
def insidePath(self, path, p): def insidePath(self, path, p):
point = pnPoint((p.x, p.y)) point = pnPoint((p.x, p.y))
pverts = [] pverts = []
@ -112,6 +118,7 @@ class Tabgen(inkex.EffectExtension):
isInside = point.InPolygon(pverts, True) isInside = point.InPolygon(pverts, True)
return isInside # True if point p is inside path return isInside # True if point p is inside path
def makescore(self, pt1, pt2, dashlength): def makescore(self, pt1, pt2, dashlength):
# Draws a dashed line of dashlength between two points # Draws a dashed line of dashlength between two points
# Dash = dashlength (in inches) space followed by dashlength mark # Dash = dashlength (in inches) space followed by dashlength mark
@ -200,17 +207,20 @@ class Tabgen(inkex.EffectExtension):
done = True done = True
return ddash return ddash
def detectIntersect(self, x1, y1, x2, y2, x3, y3, x4, y4): def detectIntersect(self, x1, y1, x2, y2, x3, y3, x4, y4):
td = (x1-x2)*(y3-y4)-(y1-y2)*(x3-x4) td = (x1-x2)*(y3-y4)-(y1-y2)*(x3-x4)
if td == 0: if td == 0:
# These line segments are parallel # These line segments are parallel
return False return False
t = ((x1-x3)*(y3-y4)-(y1-y3)*(x3-x4))/td t = ((x1-x3)*(y3-y4)-(y1-y3)*(x3-x4))/td
if (0.0 <= t) and (t <= 1.0): if (0.0 <= t) and (t <= 1.0):
return True return True
else: else:
return False return False
def makeTab(self, tpath, pt1, pt2, tabht, taba): def makeTab(self, tpath, pt1, pt2, tabht, taba):
# tpath - the pathstructure containing pt1 and pt2 # tpath - the pathstructure containing pt1 and pt2
# pt1, pt2 - the two points where the tab will be inserted # pt1, pt2 - the two points where the tab will be inserted
@ -467,6 +477,7 @@ class Tabgen(inkex.EffectExtension):
tpt1.y = thetal1[1].y tpt1.y = thetal1[1].y
tpt2.x = thetal2[1].x tpt2.x = thetal2[1].x
tpt2.y = thetal2[1].y tpt2.y = thetal2[1].y
# Check to see if any tabs intersect each other # Check to see if any tabs intersect each other
if self.detectIntersect(pt1.x, pt1.y, tpt1.x, tpt1.y, pt2.x, pt2.y, tpt2.x, tpt2.y): if self.detectIntersect(pt1.x, pt1.y, tpt1.x, tpt1.y, pt2.x, pt2.y, tpt2.x, tpt2.y):
# Found an intersection. # Found an intersection.
@ -504,10 +515,6 @@ class Tabgen(inkex.EffectExtension):
elems = [] elems = []
pc = 0 pc = 0
solidLineStyle = {'stroke': str(self.options.color_solid), 'fill': 'none', 'stroke-width': self.options.strokewidth}
dashLineStyle = {'stroke': str(self.options.color_dash), 'fill': 'none', 'stroke-width': self.options.strokewidth}
for selem in self.svg.selection.filter(inkex.PathElement): for selem in self.svg.selection.filter(inkex.PathElement):
elems.append(selem) elems.append(selem)
if len(elems) == 0: if len(elems) == 0:
@ -526,6 +533,18 @@ class Tabgen(inkex.EffectExtension):
idmod = 0 idmod = 0
elementPath = Path(elem.path.to_absolute().transform(elem.getparent().composed_transform())) elementPath = Path(elem.path.to_absolute().transform(elem.getparent().composed_transform()))
isClosed = False
raw = elementPath.to_arrays()
if raw[-1][0] == 'Z' or \
(raw[-1][0] == 'L' and raw[0][1] == raw[-1][1]) or \
(raw[-1][0] == 'C' and raw[0][1] == [raw[-1][1][-2], raw[-1][1][-1]]) \
: #if first is last point the path is also closed. The "Z" command is not required
isClosed = True
if isClosed is False:
if self.options.print_debug is True:
self.msg("Warning! Path {} is not closed. Skipping ...".format(elem.get('id')))
continue
for ptoken in elementPath: # For each point in the path for ptoken in elementPath: # For each point in the path
ptx2 = None ptx2 = None
pty2 = None pty2 = None
@ -566,12 +585,9 @@ class Tabgen(inkex.EffectExtension):
else: else:
raise inkex.AbortExtension("Unrecognized path command {0}".format(ptoken.letter)) raise inkex.AbortExtension("Unrecognized path command {0}".format(ptoken.letter))
npath.path.append(inkex.paths.Line(ptx2,pty2)) npath.path.append(inkex.paths.Line(ptx2,pty2))
npath.style = solidLineStyle
if ptoken.letter == 'Z': if ptoken.letter == 'Z':
npaths.append(npath) npaths.append(npath)
else:
if self.options.print_debug is True:
self.msg("Warning! Path {} is not closed. Skipping ...".format(elem.get('id')))
last_letter = ptoken.letter last_letter = ptoken.letter
# check for cutouts # check for cutouts
if idmod > 1: if idmod > 1:
@ -580,6 +596,7 @@ class Tabgen(inkex.EffectExtension):
if apath.id != bpath.id: if apath.id != bpath.id:
if self.pathInsidePath(bpath.path, apath.path): if self.pathInsidePath(bpath.path, apath.path):
apath.enclosed = True apath.enclosed = True
# add tabs to current path(s) # add tabs to current path(s)
if 'style' in elem.attrib: if 'style' in elem.attrib:
sstr = elem.attrib['style'] sstr = elem.attrib['style']
@ -600,6 +617,7 @@ class Tabgen(inkex.EffectExtension):
dsub = '' # Used for building sub-paths dsub = '' # Used for building sub-paths
dprop = '' # Used for building the main path dprop = '' # Used for building the main path
dscore = '' # Used for building dashlines dscore = '' # Used for building dashlines
for apath in npaths: for apath in npaths:
mpath = [apath.path[0]] # init output path with first point of input path mpath = [apath.path[0]] # init output path with first point of input path
for ptn in range(len(apath.path)-1): for ptn in range(len(apath.path)-1):
@ -628,17 +646,17 @@ class Tabgen(inkex.EffectExtension):
## and close the path ## and close the path
dsub = dsub + ' Z' dsub = dsub + ' Z'
dprop = dprop + dsub # combine all the paths dprop = dprop + dsub # combine all the paths
if math.isclose(dashlength, 0.0): # lump together all the score lines
# lump together all the score lines group = inkex.elements._groups.Group()
group = inkex.elements._groups.Group() group.label = 'group'+str(pc)+'ms'
group.label = 'group'+str(pc)+'ms' self.drawline(dprop,'model'+str(pc),group,sstr+';stroke:{}'.format(self.options.color_solid)) # Output the model
self.drawline(dprop,'model'+str(pc),group,sstr) # Output the model if dscore != '':
if dscore != '': dscore_style = sstr+';stroke:{}'.format(self.options.color_dash)
self.drawline(dscore,'score'+str(pc),group,sstr) # Output the scorelines separately if self.options.cosmetic_dash_style is True:
layer.append(group) dscore_style += ';stroke-dasharray:{}'.format(3, 3)
else: self.drawline(dscore,'score'+str(pc),group,dscore_style) # Output the scorelines separately
dprop = dprop + dscore layer.append(group)
self.drawline(dprop,savid+'ms',layer,sstr)
pc += 1 pc += 1
if self.options.keep_original is False: if self.options.keep_original is False: