Added Migrate Groups extension, some small fixes

This commit is contained in:
Mario Voigt 2020-08-13 01:28:19 +02:00
parent 9d73108224
commit 303a3f38ed
5 changed files with 104 additions and 18 deletions

View File

@ -8,9 +8,18 @@ class CleanGroups(inkex.Effect):
inkex.Effect.__init__(self) inkex.Effect.__init__(self)
def effect(self): def effect(self):
groups = self.document.xpath('//svg:g',namespaces=inkex.NSS) while True:
for group in groups: groups = self.document.xpath('//svg:g',namespaces=inkex.NSS)
if len(group.getchildren()) == 0: oldLen = len(groups)
group.getparent().remove(group) #leave the loop if there are no groups at all
if len(groups) == 0:
break
#loop trough groups. we have minimum of one to check for emptyness
for group in groups:
if len(group.getchildren()) == 0 and group.getparent() is not None:
group.getparent().remove(group) #deletes the deepest empty group
continue #we found minimum of one element to delete. so we should run another cycle to check if the parent of this group is empty after deletion
newLen = len(self.document.xpath('//svg:g',namespaces=inkex.NSS))
if newLen == oldLen: #found no more empty groups. Leaving the loop
break
CleanGroups().run() CleanGroups().run()

View File

@ -4,20 +4,20 @@
<id>fablabchemnitz.de.contour_scanner</id> <id>fablabchemnitz.de.contour_scanner</id>
<param name="main_tabs" type="notebook"> <param name="main_tabs" type="notebook">
<page name="tab_active" gui-text="Active"> <page name="tab_active" gui-text="Active">
<param name="desc" type="description">This tool helps you to find nasty contours which might bug you and prevent your work from being ready for production. It will find open contours, closed contours and self-intersecting contours. Intersecting contours can be closed or open contours so you can select this option additionally! Last ones usually happen if two or more handles (points) are coincident but which you might don't see. Or you just have large overlaps where the contour crosses itself like an 'eight' character for example. Using the highlighting it's easy to find contours with unproper path handles. Note that if you did not select any paths it will scan the whole document instead.</param> <param name="desc" type="description">This tool helps you to find nasty contours which might bug you and prevent your work from being ready for production. You can find the complete documentation at the Wiki space of https://fablabchemnitz.de</param>
<param name="help_general" type="description" appearance="header">General</param> <param name="help_general" type="description" appearance="header">General</param>
<param name="breakapart" type="bool" gui-text="Break apart contours">false</param> <param name="breakapart" type="bool" gui-text="Break apart contours">false</param>
<param name="removefillsetstroke" type="bool" gui-text="Remove fill and define stroke">false</param> <param name="removefillsetstroke" type="bool" gui-text="Remove fill and define stroke">false</param>
<param name="strokewidth" min="0.0" max="10000.0" gui-text="Stroke width (px)" type="float">1.0</param> <param name="strokewidth" min="0.0" max="10000.0" gui-text="Stroke width (px)" type="float">1.0</param>
<param name="help_highlight" type="description" appearance="header">Highlight paths</param> <param name="help_highlight" type="description" appearance="header">Highlight paths</param>
<param name="highlight_opened" type="bool" gui-text="Highlight opened contours">true</param> <param name="highlight_opened" type="bool" gui-text="Highlight opened contours">true</param>
<param name="color_opened" type="color" appearance="colorbutton" gui-text="Color opened contours">#FF0000FF</param> <param name="color_opened" type="color" appearance="colorbutton" gui-text="Color opened contours">4012452351</param>
<param name="highlight_closed" type="bool" gui-text="Highlight closed contours">true</param> <param name="highlight_closed" type="bool" gui-text="Highlight closed contours">true</param>
<param name="color_closed" type="color" appearance="colorbutton" gui-text="Color closed contours">#00FF00FF</param> <param name="color_closed" type="color" appearance="colorbutton" gui-text="Color closed contours">2330080511</param>
<param name="highlight_selfintersecting" type="bool" gui-text="Highlight self-intersecting contours">true</param> <param name="highlight_selfintersecting" type="bool" gui-text="Highlight self-intersecting contours">true</param>
<param name="color_selfintersecting" type="color" appearance="colorbutton" gui-text="Color self-intersecting contours">#0000FFFF</param> <param name="color_selfintersecting" type="color" appearance="colorbutton" gui-text="Color self-intersecting contours">1923076095</param>
<param name="highlight_intersectionpoints" type="bool" gui-text="Highlight self-intersecting points">true</param> <param name="highlight_intersectionpoints" type="bool" gui-text="Highlight self-intersecting points">true</param>
<param name="color_intersectionpoints" type="color" appearance="colorbutton" gui-text="Color self-intersecting points">#0066FFFF</param> <param name="color_intersectionpoints" type="color" appearance="colorbutton" gui-text="Color self-intersecting points">4239343359</param>
<param name="dotsize" type="int" min="0" max="10000" gui-text="Dot size (px) for self-intersecting points">10</param> <param name="dotsize" type="int" min="0" max="10000" gui-text="Dot size (px) for self-intersecting points">10</param>
<param name="help_remove" type="description" appearance="header">Remove paths</param> <param name="help_remove" type="description" appearance="header">Remove paths</param>
<param name="remove_opened" type="bool" gui-text="Remove opened contours">false</param> <param name="remove_opened" type="bool" gui-text="Remove opened contours">false</param>

View File

@ -6,17 +6,17 @@ Features
- helps to find contours which are closed or not. Good for repairing contours, closing contours,... - helps to find contours which are closed or not. Good for repairing contours, closing contours,...
- works for paths which are packed into groups or groups of groups. # - works for paths which are packed into groups or groups of groups. #
- can break contours apart like in "Path -> Break Apart" - can break contours apart like in "Path -> Break Apart"
- implements Bentley-Ottmann algorithm from https://github.com/ideasman42/isect_segments-bentley_ottmann to scan for self-intersecting paths. This only works correctly if your path is within the canvas correctly. Otherwise you might get "assert(event.in_sweep == False) AssertionError". This is commented out yet - implements Bentley-Ottmann algorithm from https://github.com/ideasman42/isect_segments-bentley_ottmann to scan for self-intersecting paths. You might get "assert(event.in_sweep == False) AssertionError". Don't know how to fix rgis
- colorized paths respective to their type - colorized paths respective to their type
- can add dots to intersection points you'd like to fix - can add dots to intersection points you'd like to fix
Author: Mario Voigt / FabLab Chemnitz Author: Mario Voigt / FabLab Chemnitz
Mail: mario.voigt@stadtfabrikanten.org Mail: mario.voigt@stadtfabrikanten.org
Date: 09.08.2020 Date: 09.08.2020
Last patch: 11.08.2020
License: GNU GPL v3 License: GNU GPL v3
""" """
import sys
from math import * from math import *
import inkex import inkex
from inkex.paths import Path, CubicSuperPath from inkex.paths import Path, CubicSuperPath
@ -25,9 +25,6 @@ from lxml import etree
import fablabchemnitz_poly_point_isect import fablabchemnitz_poly_point_isect
import copy import copy
def pout(t):
sys.exit()
def adjustStyle(self, node): def adjustStyle(self, node):
if node.attrib.has_key('style'): if node.attrib.has_key('style'):
style = node.get('style') style = node.get('style')
@ -185,9 +182,9 @@ class ContourScanner(inkex.Effect):
if self.options.remove_selfintersecting: if self.options.remove_selfintersecting:
if node.getparent() is not None: #might be already been deleted by previously checked settings so check again if node.getparent() is not None: #might be already been deleted by previously checked settings so check again
node.getparent().remove(node) node.getparent().remove(node)
except AssertionError as e: # we skip AssertionError except Exception as e: # we skip AssertionError
pass #inkex.utils.debug("Accuracy Error. Try to reduce the precision of the paths using the extension called Rounder to cutoff unrequired decimals.")
#inkex.utils.debug("Found some path which cannot be tested for self-intersecting behaviour") print(str(e))
for child in node: for child in node:
self.scanContours(child) self.scanContours(child)

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
<name>Migrate Groups</name>
<id>fablabchemnitz.de.migrategroups</id>
<effect needs-live-preview="false">
<object-type>path</object-type>
<effects-menu>
<submenu name="FabLab Chemnitz">
<submenu name="Various"/>
</submenu>
</effects-menu>
</effect>
<script>
<command reldir="extensions" interpreter="python">fablabchemnitz_migrategroups.py</command>
</script>
</inkscape-extension>

View File

@ -0,0 +1,64 @@
#!/usr/bin/env python3
"""
Extension for InkScape 1.0
This extension parses the selection and will put all paths into one single group. If you have a cluster with lots of groups and paths you will clean up this way (one top level group, all paths below it). If you select a single path or a set of paths you just wrap it like using CTRL + G (like making a usual group)
Author: Mario Voigt / FabLab Chemnitz
Mail: mario.voigt@stadtfabrikanten.org
Date: 13.08.2020
License: GNU GPL v3
"""
import inkex
class MigrateGroups(inkex.Effect):
allPaths = []
allGroups = []
def __init__(self):
inkex.Effect.__init__(self)
def effect(self):
#get all paths and groups from selection. Remove all groups from the selection and form a new single group of it
def parseNodes(self, node):
if node.tag == inkex.addNS('path','svg'):
if node not in self.allPaths:
self.allPaths.append(node)
if node.tag == inkex.addNS('g','svg'):
groups = node.getchildren()
if groups is not None:
for group in groups:
parseNodes(self, group)
if group not in self.allGroups:
self.allGroups.append(group)
for id, item in self.svg.selected.items():
parseNodes(self, item)
if len(self.allPaths) > 0:
#make a new group at root level - TODO: respect the position where the first selected object is in XML tree and put it there instead (or make this optional)
newGroup = self.document.getroot().add(inkex.Group())
#copy all paths into the new group
for path in self.allPaths:
newGroup.add(path.copy())
#then remove all the old stuff
path.getparent().remove(path)
#now remove all the obsolete groups
if len(self.allGroups) > 0:
for group in self.allGroups:
if group.getparent() is not None:
group.getparent().remove(group)
#remove the selected, now empty group (if it's the case)
if self.svg.selected[0].tag == inkex.addNS('g','svg'):
self.svg.selected[0].getparent().remove(self.svg.selected[0])
#TODO: make newGroup selected now. How ?
MigrateGroups().run()