diff --git a/extensions/fablabchemnitz/draw_directions/draw_directions.inx b/extensions/fablabchemnitz/draw_directions/draw_directions.inx
deleted file mode 100644
index 0f7a52ed..00000000
--- a/extensions/fablabchemnitz/draw_directions/draw_directions.inx
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
- Draw Directions
- fablabchemnitz.de.draw_directions
-
- path
-
-
-
-
-
-
-
-
diff --git a/extensions/fablabchemnitz/draw_directions/draw_directions.py b/extensions/fablabchemnitz/draw_directions/draw_directions.py
deleted file mode 100644
index 88024e77..00000000
--- a/extensions/fablabchemnitz/draw_directions/draw_directions.py
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/usr/bin/env python3
-
-import inkex
-from inkex.paths import Path
-from inkex import Circle
-
-class DrawDirections(inkex.EffectExtension):
-
- def drawCircle(self, group, color, point):
- style = inkex.Style({'stroke': 'none', 'fill': color})
- startCircle = group.add(Circle(cx=str(point[0]), cy=str(point[1]), r=str(self.svg.unittouu(str(self.options.dotsize/2) + "px"))))
- startCircle.style = style
-
- def add_arguments(self, pars):
- pars.add_argument("--dotsize", type=int, default=10, help="Dot size (px) for self-intersecting points")
-
- def effect(self):
- dot_group = self.svg.add(inkex.Group())
-
- for node in self.svg.selection.filter(inkex.PathElement).values():
- points = list(node.path.end_points)
- start = points[0]
- end = points[len(points) - 1]
-
- if start[0] == end[0] and start[1] == end[1]:
- self.drawCircle(dot_group, '#00FF00', start)
- self.drawCircle(dot_group, '#FFFF00', points[1]) #draw one point which gives direction of the path
- else: #open contour with start and end point
- self.drawCircle(dot_group, '#FF0000', start)
- self.drawCircle(dot_group, '#0000FF', end)
-
-if __name__ == '__main__':
- DrawDirections().run()
\ No newline at end of file
diff --git a/extensions/fablabchemnitz/draw_directions_tavel_moves/draw_directions_tavel_moves.inx b/extensions/fablabchemnitz/draw_directions_tavel_moves/draw_directions_tavel_moves.inx
new file mode 100644
index 00000000..7a8c7da1
--- /dev/null
+++ b/extensions/fablabchemnitz/draw_directions_tavel_moves/draw_directions_tavel_moves.inx
@@ -0,0 +1,56 @@
+
+
+ Draw Directions / Travel Moves
+ fablabchemnitz.de.draw_directions_tavel_moves
+
+
+ true
+ 10
+
+ false
+ false
+ true
+ true
+ 1.0
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ../000_about_fablabchemnitz.svg
+
+
+
+ path
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/extensions/fablabchemnitz/draw_directions_tavel_moves/draw_directions_tavel_moves.py b/extensions/fablabchemnitz/draw_directions_tavel_moves/draw_directions_tavel_moves.py
new file mode 100644
index 00000000..669ecb0c
--- /dev/null
+++ b/extensions/fablabchemnitz/draw_directions_tavel_moves/draw_directions_tavel_moves.py
@@ -0,0 +1,214 @@
+#!/usr/bin/env python3
+
+from lxml import etree
+import itertools
+import inkex
+from inkex import Circle, Vector2d
+from inkex.paths import Path
+from inkex.bezier import csplength
+
+class DrawDirectionsTravelMoves(inkex.EffectExtension):
+
+ def drawCircle(self, transform, group, color, point):
+ style = inkex.Style({'stroke': 'none', 'fill': color})
+ startCircle = group.add(Circle(cx=str(point[0]), cy=str(point[1]), r=str(self.svg.unittouu(str(so.dotsize/2) + "px"))))
+ startCircle.style = style
+ startCircle.transform = transform
+
+ def find_group(self, groupId):
+ ''' check if a group with a given id exists or not. Returns None if not found, else returns the group element '''
+ groups = self.document.xpath('//svg:g', namespaces=inkex.NSS)
+ for group in groups:
+ #inkex.utils.debug(str(layer.get('inkscape:label')) + " == " + layerName)
+ if group.get('id') == groupId:
+ return group
+ return None
+
+ def add_arguments(self, pars):
+ pars.add_argument("--nb_main")
+
+ pars.add_argument("--draw_dots", type=inkex.Boolean, default=True, help="Start and end point of opened (red + blue) and closed paths (green + yellow)")
+ pars.add_argument("--dotsize", type=int, default=10, help="Dot size (px)")
+ pars.add_argument("--draw_travel_moves", type=inkex.Boolean, default=False)
+ pars.add_argument("--ignore_colors", type=inkex.Boolean, default=False, help="If enabled we connect all lines by order, ignoring the stroke color (normally we have one travel line group per color)")
+ pars.add_argument("--dashed_style", type=inkex.Boolean, default=True)
+ pars.add_argument("--arrow_style", type=inkex.Boolean, default=True)
+ pars.add_argument("--arrow_size", type=float, default=True)
+ pars.add_argument("--debug", type=inkex.Boolean, default=False)
+
+ def effect(self):
+ global so
+ so = self.options
+ linePrefix = "travelLine-"
+ groupPrefix = "travelLines-"
+ ignoreWord = "ignore"
+
+ selectedPaths = [] #total list of elements to parse
+
+ def parseChildren(element):
+ if isinstance(element, inkex.PathElement) and element not in selectedPaths and linePrefix not in element.get('id') and not isinstance(element.getparent(), inkex.Marker):
+ selectedPaths.append(element)
+ children = element.getchildren()
+ if children is not None:
+ for child in children:
+ if isinstance(child, inkex.PathElement) and child not in selectedPaths and linePrefix not in element.get('id') and not isinstance(element.getparent(), inkex.Marker):
+ selectedPaths.append(child)
+ parseChildren(child) #go deeper and deeper
+
+ #check if we have selectedPaths elements or if we should parse the whole document instead
+ if len(self.svg.selected) == 0:
+ for element in self.document.getroot().iter(tag=etree.Element):
+ if isinstance(element, inkex.PathElement) and element != self.document.getroot() and linePrefix not in element.get('id') and not isinstance(element.getparent(), inkex.Marker):
+ selectedPaths.append(element)
+ else:
+ for element in self.svg.selected.values():
+ parseChildren(element)
+
+ dot_group = self.svg.add(inkex.Group())
+
+ if so.arrow_style is True:
+ markerId = "travel_move_arrow"
+ #add new marker to defs (or overwrite if existent)
+ defs = self.svg.defs
+ for defi in defs:
+ if defi.tag == "{http://www.w3.org/2000/svg}marker" and defi.get('id') == markerId: #delete
+ defi.delete()
+ marker = inkex.Marker(id=markerId)
+ marker.set("inkscape:isstock", "true")
+ marker.set("inkscape:stockid", markerId)
+ marker.set("orient", "auto")
+ marker.set("refY", "0.0")
+ marker.set("refX", "0.0")
+ marker.set("style", "overflow:visible;")
+
+ markerPath = inkex.PathElement(id=self.svg.get_unique_id('markerId-'))
+ markerPath.style = {"fill-rule": "evenodd", "fill": "context-stroke", "stroke-width": str(self.svg.unittouu('1px'))}
+ markerPath.transform = "scale(1.0,1.0) rotate(0) translate(-6.0,0)"
+ arrowHeight = 6.0
+ markerPath.attrib["transform"] = "scale({},{}) rotate(0) translate(-{},0)".format(so.arrow_size, so.arrow_size, arrowHeight)
+ markerPath.path = "M {},0.0 L -3.0,5.0 L -3.0,-5.0 L {},0.0 z".format(arrowHeight, arrowHeight)
+
+ marker.append(markerPath)
+ defs.append(marker) #do not append before letting contain it one path. Otherwise Inkscape is going to crash immediately
+
+ #collect all different stroke colors to distinguish by groups
+ strokeColors = []
+ strokeColorsAndCounts = {}
+
+ for element in selectedPaths:
+ strokeColor = element.style.get('stroke')
+ if strokeColor is None or strokeColor == "none":
+ strokeColor = "none"
+ if so.ignore_colors is True:
+ strokeColor = ignoreWord
+ strokeColors.append(strokeColor)
+ groupName = groupPrefix + strokeColor
+ travelGroup = self.find_group(groupName)
+ if travelGroup is None:
+ self.document.getroot().append(inkex.Group(id=groupName))
+ else: #exists
+ self.document.getroot().append(travelGroup)
+ for child in travelGroup:
+ child.delete()
+
+ for strokeColor in strokeColors:
+ if strokeColor in strokeColorsAndCounts:
+ strokeColorsAndCounts[strokeColor] = strokeColorsAndCounts[strokeColor] + 1
+ else:
+ strokeColorsAndCounts[strokeColor] = 1
+
+ startEndPath = [] #the container for all paths we will loop on
+ for element in selectedPaths:
+ #points = list(element.path.end_points)
+ p = element.path.transform(element.composed_transform())
+ points = list(p.end_points)
+ start = points[0]
+ end = points[len(points) - 1]
+
+ startEndPath.append([element, start, end])
+
+ #if element.getparent() != self.document.getroot():
+ # transform = element.getparent().composed_transform()
+ #else:
+ # transform = None
+ transform = None
+ if so.draw_dots is True:
+ if start[0] == end[0] and start[1] == end[1]:
+ self.drawCircle(transform, dot_group, '#00FF00', start)
+ self.drawCircle(transform, dot_group, '#FFFF00', points[1]) #draw one point which gives direction of the path
+ else: #open contour with start and end point
+ self.drawCircle(transform, dot_group, '#FF0000', start)
+ self.drawCircle(transform, dot_group, '#0000FF', end)
+
+ if so.draw_travel_moves is True:
+ for sc in strokeColorsAndCounts: #loop through all unique stroke colors
+ colorCount = strokeColorsAndCounts[sc] #the total color count per stroke color
+ ran = len(startEndPath) + 1 #one more because the last travel moves goes back to 0,0 (so for 3 elements (1,2,3) the range is 0 to 3 -> makes 4)
+ firstOccurence = True
+ createdMoves = 0
+ for i in range(0, ran): #loop through the item selection. nested loop. so we loop over alle elements again for each color
+ if i < ran - 1:
+ elementStroke = startEndPath[i][0].style.get('stroke')
+ if i == ran or createdMoves == colorCount:
+ elementStroke = startEndPath[i-1][0].style.get('stroke')
+ if elementStroke is None or elementStroke == "none":
+ elementStroke = "none"
+
+ if so.debug is True: inkex.utils.debug("current stroke color {}, element stroke color{}".format(sc, elementStroke))
+ if sc == elementStroke or sc == ignoreWord:
+ if firstOccurence is True:
+ travelStart = Vector2d(0,0)
+ firstOccurence = False
+ else:
+ if i <= ran - 1:
+ travelStart = startEndPath[i-1][2] #end point from this path
+
+ if so.debug is True: inkex.utils.debug("travelStart={}".format(travelStart))
+ if i < ran - 1:
+ travelEnd = startEndPath[i][1]
+ if createdMoves == colorCount:
+ travelEnd = Vector2d(0,0)
+
+ if so.debug is True: inkex.utils.debug("travelEnd={}".format(travelEnd))
+
+ if so.debug is True:
+ if i < ran - 1:
+ inkex.utils.debug("segment={},{}".format(startEndPath[i][2], startEndPath[i][1]))
+ if i == ran - 1:
+ inkex.utils.debug("segment={},{}".format(startEndPath[i-1][1], travelEnd))
+
+ travelLine = inkex.PathElement(id=self.svg.get_unique_id(linePrefix) + element.get('id'))
+ #if some objects are at svg:svg level this may cause errors
+ #if element.getparent() != self.document.getroot():
+ # travelLine.transform = element.getparent().composed_transform()
+ travelLine.set('d', "M{:0.6f},{:0.6f} L{:0.6f},{:0.6f}".format(travelStart[0],travelStart[1],travelEnd[0],travelEnd[1]))
+ travelLine.style = {'stroke': ("#000000" if so.ignore_colors is True else sc), 'fill': 'none', 'stroke-width': str(self.svg.unittouu('1px')), 'marker-end': 'url(#marker1426)'}
+ if so.dashed_style is True:
+ travelLine.style['stroke-dasharray'] = '1,1'
+ travelLine.style['stroke-dashoffset'] = '0'
+ if so.arrow_style is True:
+ travelLine.style["marker-end"] = "url(#{})".format(markerId)
+
+ #check the length. if zero we do not add
+ slengths, stotal = csplength(travelLine.path.transform(element.composed_transform()).to_superpath()) #get segment lengths and total length of path in document's internal unit
+ if stotal > 0:
+ #finally add the line
+ travelGroup = self.find_group(groupPrefix + sc)
+ travelGroup.add(travelLine)
+ else:
+ if so.debug is True: inkex.utils.debug("Line has length of zero")
+
+ createdMoves += 1 #each time we created a move we count up. we want to compare against the total count of that color
+ if so.debug is True: inkex.utils.debug("createdMoves={}".format(createdMoves))
+ if so.debug is True: inkex.utils.debug("-"*40)
+
+ #cleanup empty groups
+ if len(dot_group) == 0:
+ dot_group.delete()
+ travelGroups = self.document.xpath("//svg:g[starts-with(@id, 'travelLines-')]", namespaces=inkex.NSS)
+ for travelGroup in travelGroups:
+ if len(travelGroup) == 0:
+ travelGroup.delete()
+
+if __name__ == '__main__':
+ DrawDirectionsTravelMoves().run()
\ No newline at end of file
diff --git a/extensions/fablabchemnitz/draw_directions/meta.json b/extensions/fablabchemnitz/draw_directions_tavel_moves/meta.json
similarity index 61%
rename from extensions/fablabchemnitz/draw_directions/meta.json
rename to extensions/fablabchemnitz/draw_directions_tavel_moves/meta.json
index 52fc48e4..f6a95fd2 100644
--- a/extensions/fablabchemnitz/draw_directions/meta.json
+++ b/extensions/fablabchemnitz/draw_directions_tavel_moves/meta.json
@@ -1,17 +1,17 @@
[
{
- "name": "Draw Directions",
- "id": "fablabchemnitz.de.draw_directions",
+ "name": "Draw Directions / Travel Moves",
+ "id": "fablabchemnitz.de.draw_directions_travel_moces",
"path": "draw_directions",
"dependent_extensions": null,
- "original_name": "Draw Directions",
- "original_id": "fablabchemnitz.de.draw_directions",
+ "original_name": "Draw Directions / Travel Moves",
+ "original_id": "fablabchemnitz.de.draw_directions_travel_moces",
"license": "GNU GPL v3",
"license_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.X/src/branch/master/LICENSE",
"comment": "Written by Mario Voigt",
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.X/src/branch/master/extensions/fablabchemnitz/draw_directions",
"fork_url": null,
- "documentation_url": "https://stadtfabrikanten.org/display/IFM/Draw+Directions",
+ "documentation_url": "https://stadtfabrikanten.org/pages/viewpage.action?pageId=120524682",
"inkscape_gallery_url": null,
"main_authors": [
"github.com/vmario89"
diff --git a/extensions/fablabchemnitz/filter_by_length_area/filter_by_length_area.py b/extensions/fablabchemnitz/filter_by_length_area/filter_by_length_area.py
index a327d056..ad2250e7 100644
--- a/extensions/fablabchemnitz/filter_by_length_area/filter_by_length_area.py
+++ b/extensions/fablabchemnitz/filter_by_length_area/filter_by_length_area.py
@@ -161,7 +161,7 @@ class FilterByLengthArea(inkex.EffectExtension):
pass
for i in range(0, len(to_sort)):
- element = to_sort[i].get('element')
+ element = to_sort[i].get('element')
if so.delete is True:
element.delete()
diff --git a/extensions/fablabchemnitz/laser_check/laser_check.py b/extensions/fablabchemnitz/laser_check/laser_check.py
index 7239025e..173a50df 100644
--- a/extensions/fablabchemnitz/laser_check/laser_check.py
+++ b/extensions/fablabchemnitz/laser_check/laser_check.py
@@ -13,6 +13,7 @@ class LaserCheck(inkex.EffectExtension):
'''
ToDos:
+ - look for lines especially containing id "travelLines-" and sum up travel lines
- add some extra seconds for start, stop, removing parts, attaching material, ...
- maybe remove totalTravelLength and set manually ...
- Handlungsempfehlungen einbauen
@@ -36,7 +37,9 @@ class LaserCheck(inkex.EffectExtension):
- statistics
- export as PDF
- run as script to generate quick results for users
- - check for old styles which should be upgraded
+ - check for old styles which should be upgraded (cleanup styles tool)
+ - check for elements which have no style attribute (should be created) -> (cleanup styles tool)
+ - migrate styles from groups/layers to path styles (cleanup styles tool)
- self-intersecting paths
- number of parts (isles) to weed in total
- number of parts which are smaller than vector grid