Added Migrate Groups extension, some small fixes
This commit is contained in:
parent
9d73108224
commit
303a3f38ed
@ -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()
|
@ -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>
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
16
extensions/fablabchemnitz_migrategroups.inx
Normal file
16
extensions/fablabchemnitz_migrategroups.inx
Normal 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>
|
64
extensions/fablabchemnitz_migrategroups.py
Normal file
64
extensions/fablabchemnitz_migrategroups.py
Normal 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()
|
Reference in New Issue
Block a user