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