summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordoomsay <doomsay@cb376a5e-1013-0410-a455-b6b1f9ac8223>2008-10-03 19:58:20 +0000
committerdoomsay <doomsay@cb376a5e-1013-0410-a455-b6b1f9ac8223>2008-10-03 19:58:20 +0000
commit204cd4fff962e9e449e6cee3b95ca159b6610bb6 (patch)
tree394c381e88e072ff514e56731040400dc2f3329b
parent937e2d9b3d2dd6f0d43de1f7e63bf08416547ba9 (diff)
downloadreprap-backup-204cd4fff962e9e449e6cee3b95ca159b6610bb6.tar.gz
reprap-backup-204cd4fff962e9e449e6cee3b95ca159b6610bb6.zip
git-svn-id: https://reprap.svn.sourceforge.net/svnroot/reprap@2058 cb376a5e-1013-0410-a455-b6b1f9ac8223
-rw-r--r--trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge.html6
-rw-r--r--trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.analyze_plugins.vectorwrite.html4
-rw-r--r--trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.comb.html52
-rw-r--r--trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.hop.html4
-rw-r--r--trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.html6
-rw-r--r--trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.nozzle_wipe.html3
-rw-r--r--trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.raft.html7
-rw-r--r--trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.skeinforge_utilities.euclidean.html4
-rw-r--r--trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.skeinforge_utilities.intercircle.html1
-rw-r--r--trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.slice_shape.html6
-rw-r--r--trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.tower.html4
-rw-r--r--trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge.py8
-rw-r--r--trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/analyze_plugins/skeinview.py5
-rw-r--r--trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/analyze_plugins/vectorwrite.py45
-rw-r--r--trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/comb.py354
-rw-r--r--trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/fill.py25
-rw-r--r--trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/hop.py6
-rw-r--r--trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/nozzle_wipe.py16
-rw-r--r--trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/raft.py23
-rw-r--r--trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/skeinforge_utilities/euclidean.py71
-rw-r--r--trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/skeinforge_utilities/gcodec.py11
-rw-r--r--trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/skeinforge_utilities/intercircle.py30
-rw-r--r--trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/slice_shape.py129
-rw-r--r--trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/stretch.py31
-rw-r--r--trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/tower.py4
25 files changed, 606 insertions, 249 deletions
diff --git a/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge.html b/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge.html
index 12b891a1..a8d61ca3 100644
--- a/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge.html
+++ b/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge.html
@@ -171,6 +171,12 @@ https://reprap.svn.sourceforge.net/svnroot/reprap/trunk/reprap/miscellaneous/pyt
&nbsp;<br>
&nbsp;<br>
&nbsp;<br>
+Motto<br>
+&nbsp;<br>
+I&nbsp;may&nbsp;be&nbsp;slow,&nbsp;but&nbsp;I&nbsp;get&nbsp;there&nbsp;in&nbsp;the&nbsp;end.<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
Troubleshooting<br>
&nbsp;<br>
You&nbsp;can&nbsp;ask&nbsp;for&nbsp;skeinforge&nbsp;help&nbsp;by&nbsp;posting&nbsp;in&nbsp;the&nbsp;"How&nbsp;to&nbsp;Print&nbsp;Gcode&nbsp;from&nbsp;Host"&nbsp;thread&nbsp;at:<br>
diff --git a/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.analyze_plugins.vectorwrite.html b/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.analyze_plugins.vectorwrite.html
index e77f1d5f..7f64517a 100644
--- a/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.analyze_plugins.vectorwrite.html
+++ b/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.analyze_plugins.vectorwrite.html
@@ -110,8 +110,6 @@ The&nbsp;vector&nbsp;file&nbsp;is&nbsp;saved&nbsp;as&nbsp;Screw&nbsp;Holder.svg<
<td width="100%">Methods defined here:<br>
<dl><dt><a name="VectorwritePreferences-__init__"><strong>__init__</strong></a>(self)</dt><dd><tt>Set&nbsp;the&nbsp;default&nbsp;preferences,&nbsp;execute&nbsp;title&nbsp;&amp;&nbsp;preferences&nbsp;filename.</tt></dd></dl>
-<dl><dt><a name="VectorwritePreferences-execute"><strong>execute</strong></a>(self)</dt><dd><tt>Write&nbsp;button&nbsp;has&nbsp;been&nbsp;clicked.</tt></dd></dl>
-
</td></tr></table> <p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#ffc8d8">
@@ -128,6 +126,8 @@ The&nbsp;vector&nbsp;file&nbsp;is&nbsp;saved&nbsp;as&nbsp;Screw&nbsp;Holder.svg<
<dl><dt><a name="VectorwriteSkein-addVectorWindow"><strong>addVectorWindow</strong></a>(self)</dt><dd><tt>Add&nbsp;a&nbsp;new&nbsp;vector&nbsp;window&nbsp;to&nbsp;vector&nbsp;windows.</tt></dd></dl>
+<dl><dt><a name="VectorwriteSkein-execute"><strong>execute</strong></a>(self)</dt><dd><tt>Write&nbsp;button&nbsp;has&nbsp;been&nbsp;clicked.</tt></dd></dl>
+
<dl><dt><a name="VectorwriteSkein-getFilenameWriteFiles"><strong>getFilenameWriteFiles</strong></a>(self, filename)</dt><dd><tt>Write&nbsp;one&nbsp;or&nbsp;multiple&nbsp;files&nbsp;for&nbsp;the&nbsp;filename.</tt></dd></dl>
<dl><dt><a name="VectorwriteSkein-getHypertextLinkBasename"><strong>getHypertextLinkBasename</strong></a>(self, baseUnderscoredPrefix, vectorWindowIndex)</dt><dd><tt>Get&nbsp;hypertext&nbsp;link&nbsp;basename&nbsp;for&nbsp;a&nbsp;numbered&nbsp;vector&nbsp;window.</tt></dd></dl>
diff --git a/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.comb.html b/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.comb.html
index 8e02e393..b2c25497 100644
--- a/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.comb.html
+++ b/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.comb.html
@@ -11,9 +11,13 @@
><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/enrique/Desktop/backup/babbleold/script/reprap/pyRepRap/skeinforge_tools/comb.py">/home/enrique/Desktop/backup/babbleold/script/reprap/pyRepRap/skeinforge_tools/comb.py</a></font></td></tr></table>
<p><tt>Comb&nbsp;is&nbsp;a&nbsp;script&nbsp;to&nbsp;comb&nbsp;the&nbsp;extrusion&nbsp;hair&nbsp;of&nbsp;a&nbsp;gcode&nbsp;file.<br>
&nbsp;<br>
-Comb&nbsp;bends&nbsp;the&nbsp;extruder&nbsp;travel&nbsp;paths&nbsp;around&nbsp;holes&nbsp;in&nbsp;the&nbsp;slice,&nbsp;to&nbsp;avoid&nbsp;stringers.&nbsp;&nbsp;The&nbsp;default&nbsp;'Activate&nbsp;Comb'&nbsp;checkbox&nbsp;is&nbsp;on.<br>
-When&nbsp;it's&nbsp;on&nbsp;the&nbsp;paths&nbsp;are&nbsp;bent.&nbsp;&nbsp;When&nbsp;it&nbsp;is&nbsp;off,&nbsp;this&nbsp;script&nbsp;does&nbsp;nothing,&nbsp;the&nbsp;gcode&nbsp;text&nbsp;is&nbsp;handed&nbsp;over&nbsp;the&nbsp;next&nbsp;tool&nbsp;in&nbsp;the<br>
-skeinforge&nbsp;chain.&nbsp;&nbsp;To&nbsp;run&nbsp;comb,&nbsp;in&nbsp;a&nbsp;shell&nbsp;type:<br>
+The&nbsp;default&nbsp;'Activate&nbsp;Comb'&nbsp;checkbox&nbsp;is&nbsp;on.&nbsp;&nbsp;When&nbsp;it&nbsp;is&nbsp;on,&nbsp;the&nbsp;functions&nbsp;described&nbsp;below&nbsp;will&nbsp;work,&nbsp;when&nbsp;it&nbsp;is&nbsp;off,&nbsp;the&nbsp;functions<br>
+will&nbsp;not&nbsp;be&nbsp;called.<br>
+&nbsp;<br>
+Comb&nbsp;bends&nbsp;the&nbsp;extruder&nbsp;travel&nbsp;paths&nbsp;around&nbsp;holes&nbsp;in&nbsp;the&nbsp;slice,&nbsp;to&nbsp;avoid&nbsp;stringers&nbsp;and&nbsp;it&nbsp;jitters&nbsp;the&nbsp;loop&nbsp;end&nbsp;position&nbsp;to&nbsp;a&nbsp;different<br>
+place&nbsp;on&nbsp;each&nbsp;layer&nbsp;to&nbsp;prevent&nbsp;the&nbsp;a&nbsp;ridge&nbsp;from&nbsp;forming.&nbsp;&nbsp;The&nbsp;"Jitter&nbsp;Over&nbsp;Extrusion&nbsp;Width&nbsp;(ratio)"&nbsp;is&nbsp;the&nbsp;ratio&nbsp;of&nbsp;the&nbsp;amount&nbsp;the<br>
+loop&nbsp;ends&nbsp;will&nbsp;be&nbsp;jittered.&nbsp;&nbsp;A&nbsp;high&nbsp;value&nbsp;means&nbsp;the&nbsp;loops&nbsp;will&nbsp;start&nbsp;all&nbsp;over&nbsp;the&nbsp;place&nbsp;and&nbsp;a&nbsp;low&nbsp;value&nbsp;means&nbsp;loops&nbsp;will&nbsp;start&nbsp;at<br>
+roughly&nbsp;the&nbsp;same&nbsp;place&nbsp;on&nbsp;each&nbsp;layer.&nbsp;&nbsp;To&nbsp;run&nbsp;comb,&nbsp;in&nbsp;a&nbsp;shell&nbsp;type:<br>
&gt;&nbsp;python&nbsp;comb.py<br>
&nbsp;<br>
The&nbsp;following&nbsp;examples&nbsp;comb&nbsp;the&nbsp;files&nbsp;Hollow&nbsp;Square.gcode&nbsp;&amp;&nbsp;Hollow&nbsp;Square.gts.&nbsp;&nbsp;The&nbsp;examples&nbsp;are&nbsp;run&nbsp;in&nbsp;a&nbsp;terminal&nbsp;in&nbsp;the&nbsp;folder<br>
@@ -21,7 +25,8 @@ which&nbsp;contains&nbsp;Hollow&nbsp;Square.gcode,&nbsp;Hollow&nbsp;Square.gts&n
can&nbsp;be&nbsp;set&nbsp;in&nbsp;the&nbsp;dialog&nbsp;or&nbsp;by&nbsp;changing&nbsp;the&nbsp;preferences&nbsp;file&nbsp;'comb.csv'&nbsp;in&nbsp;the&nbsp;'.skeinforge'&nbsp;folder&nbsp;in&nbsp;your&nbsp;home&nbsp;directory&nbsp;with&nbsp;a&nbsp;text<br>
editor&nbsp;or&nbsp;a&nbsp;spreadsheet&nbsp;program&nbsp;set&nbsp;to&nbsp;separate&nbsp;tabs.&nbsp;&nbsp;The&nbsp;functions&nbsp;writeOutput&nbsp;and&nbsp;getCombChainGcode&nbsp;check&nbsp;to&nbsp;see&nbsp;if&nbsp;the<br>
text&nbsp;has&nbsp;been&nbsp;combed,&nbsp;if&nbsp;not&nbsp;they&nbsp;call&nbsp;getTowerChainGcode&nbsp;in&nbsp;tower.py&nbsp;to&nbsp;tower&nbsp;the&nbsp;text;&nbsp;once&nbsp;they&nbsp;have&nbsp;the&nbsp;towered&nbsp;text,&nbsp;then<br>
-they&nbsp;comb.<br>
+they&nbsp;comb.&nbsp;&nbsp;Pictures&nbsp;of&nbsp;combing&nbsp;in&nbsp;action&nbsp;are&nbsp;available&nbsp;from&nbsp;the&nbsp;Metalab&nbsp;blog&nbsp;at:<br>
+<a href="http://reprap.soup.io/?search=combing">http://reprap.soup.io/?search=combing</a><br>
&nbsp;<br>
&nbsp;<br>
&gt;&nbsp;python&nbsp;comb.py<br>
@@ -71,15 +76,16 @@ many&nbsp;lines&nbsp;of&nbsp;gcode<br>
<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="__init__.html">__init__</a><br>
<a href="skeinforge_tools.analyze.html">skeinforge_tools.analyze</a><br>
<a href="cStringIO.html">cStringIO</a><br>
-</td><td width="25%" valign=top><a href="skeinforge_tools.skeinforge_utilities.euclidean.html">skeinforge_tools.skeinforge_utilities.euclidean</a><br>
-<a href="skeinforge_tools.skeinforge_utilities.gcodec.html">skeinforge_tools.skeinforge_utilities.gcodec</a><br>
+<a href="skeinforge_tools.skeinforge_utilities.euclidean.html">skeinforge_tools.skeinforge_utilities.euclidean</a><br>
+</td><td width="25%" valign=top><a href="skeinforge_tools.skeinforge_utilities.gcodec.html">skeinforge_tools.skeinforge_utilities.gcodec</a><br>
<a href="skeinforge_tools.import_translator.html">skeinforge_tools.import_translator</a><br>
-</td><td width="25%" valign=top><a href="skeinforge_tools.skeinforge_utilities.intercircle.html">skeinforge_tools.skeinforge_utilities.intercircle</a><br>
-<a href="skeinforge_tools.polyfile.html">skeinforge_tools.polyfile</a><br>
+<a href="skeinforge_tools.skeinforge_utilities.intercircle.html">skeinforge_tools.skeinforge_utilities.intercircle</a><br>
+<a href="math.html">math</a><br>
+</td><td width="25%" valign=top><a href="skeinforge_tools.polyfile.html">skeinforge_tools.polyfile</a><br>
<a href="skeinforge_tools.skeinforge_utilities.preferences.html">skeinforge_tools.skeinforge_utilities.preferences</a><br>
-</td><td width="25%" valign=top><a href="sys.html">sys</a><br>
+<a href="sys.html">sys</a><br>
<a href="time.html">time</a><br>
-<a href="skeinforge_tools.tower.html">skeinforge_tools.tower</a><br>
+</td><td width="25%" valign=top><a href="skeinforge_tools.tower.html">skeinforge_tools.tower</a><br>
</td></tr></table></td></tr></table><p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#ee77aa">
@@ -117,29 +123,51 @@ many&nbsp;lines&nbsp;of&nbsp;gcode<br>
<td width="100%">Methods defined here:<br>
<dl><dt><a name="CombSkein-__init__"><strong>__init__</strong></a>(self)</dt></dl>
+<dl><dt><a name="CombSkein-addGcodeFromThread"><strong>addGcodeFromThread</strong></a>(self, thread)</dt><dd><tt>Add&nbsp;a&nbsp;gcode&nbsp;thread&nbsp;to&nbsp;the&nbsp;output.</tt></dd></dl>
+
<dl><dt><a name="CombSkein-addGcodeMovement"><strong>addGcodeMovement</strong></a>(self, point)</dt><dd><tt>Add&nbsp;a&nbsp;movement&nbsp;to&nbsp;the&nbsp;output.</tt></dd></dl>
<dl><dt><a name="CombSkein-addIfTravel"><strong>addIfTravel</strong></a>(self, splitLine)</dt><dd><tt>Add&nbsp;travel&nbsp;move&nbsp;around&nbsp;loops&nbsp;if&nbsp;this&nbsp;the&nbsp;extruder&nbsp;is&nbsp;off.</tt></dd></dl>
<dl><dt><a name="CombSkein-addLine"><strong>addLine</strong></a>(self, line)</dt><dd><tt>Add&nbsp;a&nbsp;line&nbsp;of&nbsp;text&nbsp;and&nbsp;a&nbsp;newline&nbsp;to&nbsp;the&nbsp;output.</tt></dd></dl>
+<dl><dt><a name="CombSkein-addPathBeforeEnd"><strong>addPathBeforeEnd</strong></a>(self, loop)</dt><dd><tt>Add&nbsp;the&nbsp;path&nbsp;before&nbsp;the&nbsp;end&nbsp;of&nbsp;the&nbsp;loop.</tt></dd></dl>
+
<dl><dt><a name="CombSkein-addPathBetween"><strong>addPathBetween</strong></a>(self, betweenFirst, betweenSecond, loopFirst)</dt><dd><tt>Add&nbsp;a&nbsp;path&nbsp;between&nbsp;the&nbsp;perimeter&nbsp;and&nbsp;the&nbsp;fill.</tt></dd></dl>
+<dl><dt><a name="CombSkein-addTailoredLoopPath"><strong>addTailoredLoopPath</strong></a>(self)</dt><dd><tt>Add&nbsp;a&nbsp;clipped&nbsp;and&nbsp;jittered&nbsp;loop&nbsp;path.</tt></dd></dl>
+
<dl><dt><a name="CombSkein-addToLoop"><strong>addToLoop</strong></a>(self, location)</dt><dd><tt>Add&nbsp;a&nbsp;location&nbsp;to&nbsp;loop.</tt></dd></dl>
<dl><dt><a name="CombSkein-getBetweens"><strong>getBetweens</strong></a>(self)</dt><dd><tt>Set&nbsp;betweens&nbsp;for&nbsp;the&nbsp;layer.</tt></dd></dl>
+<dl><dt><a name="CombSkein-getJitteredLoop"><strong>getJitteredLoop</strong></a>(self, jitterDistance, jitterLoop)</dt><dd><tt>Get&nbsp;a&nbsp;jittered&nbsp;loop&nbsp;path.</tt></dd></dl>
+
<dl><dt><a name="CombSkein-getOutloopLocation"><strong>getOutloopLocation</strong></a>(self, point)</dt><dd><tt>Get&nbsp;location&nbsp;outside&nbsp;of&nbsp;loop.</tt></dd></dl>
<dl><dt><a name="CombSkein-getRounded"><strong>getRounded</strong></a>(self, number)</dt><dd><tt>Get&nbsp;number&nbsp;rounded&nbsp;to&nbsp;the&nbsp;number&nbsp;of&nbsp;carried&nbsp;decimal&nbsp;places&nbsp;as&nbsp;a&nbsp;string.</tt></dd></dl>
+<dl><dt><a name="CombSkein-initializeMoreParameters"><strong>initializeMoreParameters</strong></a>(self)</dt><dd><tt>Add&nbsp;a&nbsp;movement&nbsp;to&nbsp;the&nbsp;output.</tt></dd></dl>
+
+<dl><dt><a name="CombSkein-insertPathsAroundBetween"><strong>insertPathsAroundBetween</strong></a>(self, location)</dt><dd><tt>Insert&nbsp;paths&nbsp;around&nbsp;and&nbsp;between&nbsp;the&nbsp;perimeter&nbsp;and&nbsp;the&nbsp;fill.</tt></dd></dl>
+
<dl><dt><a name="CombSkein-insertPathsBetween"><strong>insertPathsBetween</strong></a>(self, nextBeginning, pathEnd)</dt><dd><tt>Insert&nbsp;paths&nbsp;between&nbsp;the&nbsp;perimeter&nbsp;and&nbsp;the&nbsp;fill.</tt></dd></dl>
+<dl><dt><a name="CombSkein-isClose"><strong>isClose</strong></a>(self, locationFirst, locationSecond)</dt><dd><tt>Determine&nbsp;if&nbsp;the&nbsp;first&nbsp;location&nbsp;is&nbsp;close&nbsp;to&nbsp;the&nbsp;second&nbsp;location.</tt></dd></dl>
+
+<dl><dt><a name="CombSkein-isNextExtruderOn"><strong>isNextExtruderOn</strong></a>(self)</dt><dd><tt>Determine&nbsp;if&nbsp;there&nbsp;is&nbsp;an&nbsp;extruder&nbsp;on&nbsp;command&nbsp;before&nbsp;a&nbsp;move&nbsp;command.</tt></dd></dl>
+
+<dl><dt><a name="CombSkein-linearMove"><strong>linearMove</strong></a>(self, splitLine)</dt><dd><tt>Add&nbsp;to&nbsp;loop&nbsp;path&nbsp;if&nbsp;this&nbsp;is&nbsp;a&nbsp;loop&nbsp;or&nbsp;path.</tt></dd></dl>
+
+<dl><dt><a name="CombSkein-parseAddJitter"><strong>parseAddJitter</strong></a>(self, line)</dt><dd><tt>Parse&nbsp;a&nbsp;gcode&nbsp;line,&nbsp;jitter&nbsp;it&nbsp;and&nbsp;add&nbsp;it&nbsp;to&nbsp;the&nbsp;comb&nbsp;skein.</tt></dd></dl>
+
<dl><dt><a name="CombSkein-parseAddTravel"><strong>parseAddTravel</strong></a>(self, line)</dt><dd><tt>Parse&nbsp;a&nbsp;gcode&nbsp;line&nbsp;and&nbsp;add&nbsp;it&nbsp;to&nbsp;the&nbsp;comb&nbsp;skein.</tt></dd></dl>
-<dl><dt><a name="CombSkein-parseGcode"><strong>parseGcode</strong></a>(self, gcodeText)</dt><dd><tt>Parse&nbsp;gcode&nbsp;text&nbsp;and&nbsp;store&nbsp;the&nbsp;comb&nbsp;gcode.</tt></dd></dl>
+<dl><dt><a name="CombSkein-parseGcode"><strong>parseGcode</strong></a>(self, combPreferences, gcodeText)</dt><dd><tt>Parse&nbsp;gcode&nbsp;text&nbsp;and&nbsp;store&nbsp;the&nbsp;comb&nbsp;gcode.</tt></dd></dl>
+
+<dl><dt><a name="CombSkein-parseInitialization"><strong>parseInitialization</strong></a>(self, combPreferences)</dt><dd><tt>Parse&nbsp;gcode&nbsp;initialization&nbsp;and&nbsp;store&nbsp;the&nbsp;parameters.</tt></dd></dl>
-<dl><dt><a name="CombSkein-parseLine"><strong>parseLine</strong></a>(self, line)</dt><dd><tt>Parse&nbsp;a&nbsp;gcode&nbsp;line.</tt></dd></dl>
+<dl><dt><a name="CombSkein-parseLine"><strong>parseLine</strong></a>(self, combPreferences, line)</dt><dd><tt>Parse&nbsp;a&nbsp;gcode&nbsp;line.</tt></dd></dl>
</td></tr></table></td></tr></table><p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
diff --git a/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.hop.html b/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.hop.html
index ca2193ae..edc6b134 100644
--- a/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.hop.html
+++ b/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.hop.html
@@ -11,8 +11,8 @@
><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/enrique/Desktop/backup/babbleold/script/reprap/pyRepRap/skeinforge_tools/hop.py">/home/enrique/Desktop/backup/babbleold/script/reprap/pyRepRap/skeinforge_tools/hop.py</a></font></td></tr></table>
<p><tt>Hop&nbsp;is&nbsp;a&nbsp;script&nbsp;to&nbsp;raise&nbsp;the&nbsp;extruder&nbsp;when&nbsp;it&nbsp;is&nbsp;not&nbsp;extruding.<br>
&nbsp;<br>
-The&nbsp;default&nbsp;'Activate&nbsp;Hop'&nbsp;checkbox&nbsp;is&nbsp;on.&nbsp;&nbsp;When&nbsp;it&nbsp;is&nbsp;on,&nbsp;the&nbsp;functions&nbsp;described&nbsp;below&nbsp;will&nbsp;work,&nbsp;when&nbsp;it&nbsp;is&nbsp;off,&nbsp;the&nbsp;functions<br>
-will&nbsp;not&nbsp;be&nbsp;called.<br>
+The&nbsp;default&nbsp;'Activate&nbsp;Hop'&nbsp;checkbox&nbsp;is&nbsp;off.&nbsp;&nbsp;It&nbsp;is&nbsp;off&nbsp;because&nbsp;Vik&nbsp;and&nbsp;Nophead&nbsp;found&nbsp;better&nbsp;results&nbsp;without&nbsp;hopping.&nbsp;&nbsp;When&nbsp;it<br>
+is&nbsp;on,&nbsp;the&nbsp;functions&nbsp;described&nbsp;below&nbsp;will&nbsp;work,&nbsp;when&nbsp;it&nbsp;is&nbsp;off,&nbsp;the&nbsp;functions&nbsp;will&nbsp;not&nbsp;be&nbsp;called.<br>
&nbsp;<br>
The&nbsp;important&nbsp;value&nbsp;for&nbsp;the&nbsp;hop&nbsp;preferences&nbsp;is&nbsp;"Hop&nbsp;Over&nbsp;Extrusion&nbsp;Height&nbsp;(ratio)"&nbsp;which&nbsp;is&nbsp;the&nbsp;ratio&nbsp;of&nbsp;the&nbsp;hop&nbsp;height&nbsp;over&nbsp;the<br>
extrusion&nbsp;height,&nbsp;the&nbsp;default&nbsp;is&nbsp;1.0.&nbsp;&nbsp;The&nbsp;'Minimum&nbsp;Hop&nbsp;Angle&nbsp;(degrees)'&nbsp;is&nbsp;the&nbsp;minimum&nbsp;angle&nbsp;that&nbsp;the&nbsp;path&nbsp;of&nbsp;the&nbsp;extruder<br>
diff --git a/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.html b/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.html
index 8108b424..0aa19ac0 100644
--- a/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.html
+++ b/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.html
@@ -19,16 +19,16 @@
<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="skeinforge_tools.analyze.html">analyze</a><br>
<a href="skeinforge_tools.analyze_plugins.html"><strong>analyze_plugins</strong>&nbsp;(package)</a><br>
+<a href="skeinforge_tools.clip.html">clip</a><br>
<a href="skeinforge_tools.comb.html">comb</a><br>
<a href="skeinforge_tools.cool.html">cool</a><br>
<a href="skeinforge_tools.export.html">export</a><br>
-<a href="skeinforge_tools.export_plugins.html"><strong>export_plugins</strong>&nbsp;(package)</a><br>
-</td><td width="25%" valign=top><a href="skeinforge_tools.fill.html">fill</a><br>
+</td><td width="25%" valign=top><a href="skeinforge_tools.export_plugins.html"><strong>export_plugins</strong>&nbsp;(package)</a><br>
+<a href="skeinforge_tools.fill.html">fill</a><br>
<a href="skeinforge_tools.fillet.html">fillet</a><br>
<a href="skeinforge_tools.hop.html">hop</a><br>
<a href="skeinforge_tools.import_plugins.html"><strong>import_plugins</strong>&nbsp;(package)</a><br>
<a href="skeinforge_tools.import_translator.html">import_translator</a><br>
-<a href="skeinforge_tools.loop_tailor.html">loop_tailor</a><br>
</td><td width="25%" valign=top><a href="skeinforge_tools.material.html">material</a><br>
<a href="skeinforge_tools.nozzle_wipe.html">nozzle_wipe</a><br>
<a href="skeinforge_tools.oozebane.html">oozebane</a><br>
diff --git a/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.nozzle_wipe.html b/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.nozzle_wipe.html
index d2786e57..0e1a2894 100644
--- a/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.nozzle_wipe.html
+++ b/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.nozzle_wipe.html
@@ -155,8 +155,7 @@ Many&nbsp;line&nbsp;of&nbsp;nozzle&nbsp;wiped&nbsp;gcode.</tt></p>
<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
-<td width="100%"><dl><dt><a name="-getIntermediateLocation"><strong>getIntermediateLocation</strong></a>(alongWay, begin, end)</dt><dd><tt>Get&nbsp;the&nbsp;intermediate&nbsp;location&nbsp;between&nbsp;begin&nbsp;and&nbsp;end.</tt></dd></dl>
- <dl><dt><a name="-getNozzleWipeChainGcode"><strong>getNozzleWipeChainGcode</strong></a>(filename, gcodeText, nozzleWipePreferences<font color="#909090">=None</font>)</dt><dd><tt>Nozzle&nbsp;wipe&nbsp;a&nbsp;gcode&nbsp;linear&nbsp;move&nbsp;text.&nbsp;&nbsp;Chain&nbsp;nozzle&nbsp;wipe&nbsp;the&nbsp;gcode&nbsp;if&nbsp;it&nbsp;is&nbsp;not&nbsp;already&nbsp;nozzle&nbsp;wiped.</tt></dd></dl>
+<td width="100%"><dl><dt><a name="-getNozzleWipeChainGcode"><strong>getNozzleWipeChainGcode</strong></a>(filename, gcodeText, nozzleWipePreferences<font color="#909090">=None</font>)</dt><dd><tt>Nozzle&nbsp;wipe&nbsp;a&nbsp;gcode&nbsp;linear&nbsp;move&nbsp;text.&nbsp;&nbsp;Chain&nbsp;nozzle&nbsp;wipe&nbsp;the&nbsp;gcode&nbsp;if&nbsp;it&nbsp;is&nbsp;not&nbsp;already&nbsp;nozzle&nbsp;wiped.</tt></dd></dl>
<dl><dt><a name="-getNozzleWipeGcode"><strong>getNozzleWipeGcode</strong></a>(gcodeText, nozzleWipePreferences<font color="#909090">=None</font>)</dt><dd><tt>Nozzle&nbsp;wipe&nbsp;a&nbsp;gcode&nbsp;linear&nbsp;move&nbsp;text.</tt></dd></dl>
<dl><dt><a name="-main"><strong>main</strong></a>(hashtable<font color="#909090">=None</font>)</dt><dd><tt>Display&nbsp;the&nbsp;nozzle&nbsp;wipe&nbsp;dialog.</tt></dd></dl>
<dl><dt><a name="-writeOutput"><strong>writeOutput</strong></a>(filename<font color="#909090">=''</font>)</dt><dd><tt>Nozzle&nbsp;wipe&nbsp;a&nbsp;gcode&nbsp;linear&nbsp;move&nbsp;file.&nbsp;&nbsp;Chain&nbsp;nozzle&nbsp;wipe&nbsp;the&nbsp;gcode&nbsp;if&nbsp;it&nbsp;is&nbsp;not&nbsp;already&nbsp;nozzle&nbsp;wiped.&nbsp;If&nbsp;no&nbsp;filename&nbsp;is&nbsp;specified,&nbsp;nozzle&nbsp;wipe&nbsp;the&nbsp;first&nbsp;unmodified&nbsp;gcode&nbsp;file&nbsp;in&nbsp;this&nbsp;folder.</tt></dd></dl>
diff --git a/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.raft.html b/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.raft.html
index 936a33ce..e10f8dcf 100644
--- a/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.raft.html
+++ b/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.raft.html
@@ -73,8 +73,9 @@ The&nbsp;following&nbsp;examples&nbsp;raft&nbsp;the&nbsp;files&nbsp;Hollow&nbsp;
which&nbsp;contains&nbsp;Hollow&nbsp;Square.gcode,&nbsp;Hollow&nbsp;Square.gts&nbsp;and&nbsp;raft.py.&nbsp;&nbsp;The&nbsp;raft&nbsp;function&nbsp;will&nbsp;raft&nbsp;if<br>
"Activate&nbsp;Raft,&nbsp;Elevate&nbsp;Nozzle,&nbsp;Orbit&nbsp;and&nbsp;Set&nbsp;Altitude"&nbsp;is&nbsp;true,&nbsp;which&nbsp;can&nbsp;be&nbsp;set&nbsp;in&nbsp;the&nbsp;dialog&nbsp;or&nbsp;by&nbsp;changing&nbsp;the&nbsp;preferences&nbsp;file<br>
'raft.csv'&nbsp;with&nbsp;a&nbsp;text&nbsp;editor&nbsp;or&nbsp;a&nbsp;spreadsheet&nbsp;program&nbsp;set&nbsp;to&nbsp;separate&nbsp;tabs.&nbsp;&nbsp;The&nbsp;functions&nbsp;writeOutput&nbsp;and&nbsp;getRaftChainGcode<br>
-check&nbsp;to&nbsp;see&nbsp;if&nbsp;the&nbsp;text&nbsp;has&nbsp;been&nbsp;rafted,&nbsp;if&nbsp;not&nbsp;they&nbsp;call&nbsp;getCombChainGcode&nbsp;in&nbsp;comb.py&nbsp;to&nbsp;get&nbsp;combed&nbsp;gcode;&nbsp;once&nbsp;they&nbsp;have<br>
-the&nbsp;combed&nbsp;text,&nbsp;then&nbsp;they&nbsp;raft.<br>
+check&nbsp;to&nbsp;see&nbsp;if&nbsp;the&nbsp;text&nbsp;has&nbsp;been&nbsp;rafted,&nbsp;if&nbsp;not&nbsp;they&nbsp;call&nbsp;getClipChainGcode&nbsp;in&nbsp;clip.py&nbsp;to&nbsp;get&nbsp;clipped&nbsp;gcode;&nbsp;once&nbsp;they&nbsp;have<br>
+the&nbsp;clipped&nbsp;text,&nbsp;then&nbsp;they&nbsp;raft.&nbsp;&nbsp;Pictures&nbsp;of&nbsp;rafting&nbsp;in&nbsp;action&nbsp;are&nbsp;available&nbsp;from&nbsp;the&nbsp;Metalab&nbsp;blog&nbsp;at:<br>
+<a href="http://reprap.soup.io/?search=rafting">http://reprap.soup.io/?search=rafting</a><br>
&nbsp;<br>
&nbsp;<br>
&gt;&nbsp;python&nbsp;raft.py<br>
@@ -124,7 +125,7 @@ many&nbsp;lines&nbsp;of&nbsp;gcode<br>
<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="__init__.html">__init__</a><br>
<a href="skeinforge_tools.analyze.html">skeinforge_tools.analyze</a><br>
<a href="cStringIO.html">cStringIO</a><br>
-<a href="skeinforge_tools.comb.html">skeinforge_tools.comb</a><br>
+<a href="skeinforge_tools.clip.html">skeinforge_tools.clip</a><br>
</td><td width="25%" valign=top><a href="skeinforge_tools.skeinforge_utilities.euclidean.html">skeinforge_tools.skeinforge_utilities.euclidean</a><br>
<a href="skeinforge_tools.skeinforge_utilities.gcodec.html">skeinforge_tools.skeinforge_utilities.gcodec</a><br>
<a href="skeinforge_tools.import_translator.html">skeinforge_tools.import_translator</a><br>
diff --git a/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.skeinforge_utilities.euclidean.html b/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.skeinforge_utilities.euclidean.html
index eb8fe87d..142d2a86 100644
--- a/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.skeinforge_utilities.euclidean.html
+++ b/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.skeinforge_utilities.euclidean.html
@@ -136,6 +136,7 @@ subtractFromVec3&nbsp;--&nbsp;Vec3&nbsp;whose&nbsp;angle&nbsp;will&nbsp;be&nbsp;
subtractVec3&nbsp;--&nbsp;Vec3&nbsp;whose&nbsp;angle&nbsp;will&nbsp;be&nbsp;subtracted</tt></dd></dl>
<dl><dt><a name="-getAroundLoop"><strong>getAroundLoop</strong></a>(begin, end, loop)</dt><dd><tt>Get&nbsp;an&nbsp;arc&nbsp;around&nbsp;a&nbsp;loop.</tt></dd></dl>
<dl><dt><a name="-getAwayPath"><strong>getAwayPath</strong></a>(path, radius)</dt><dd><tt>Get&nbsp;a&nbsp;loop&nbsp;with&nbsp;only&nbsp;the&nbsp;points&nbsp;that&nbsp;are&nbsp;far&nbsp;enough&nbsp;away&nbsp;from&nbsp;each&nbsp;other.</tt></dd></dl>
+ <dl><dt><a name="-getClippedLoopPath"><strong>getClippedLoopPath</strong></a>(clip, loopPath)</dt><dd><tt>Get&nbsp;a&nbsp;clipped&nbsp;loop&nbsp;path.</tt></dd></dl>
<dl><dt><a name="-getComplexCrossProduct"><strong>getComplexCrossProduct</strong></a>(firstComplex, secondComplex)</dt><dd><tt>Get&nbsp;z&nbsp;component&nbsp;cross&nbsp;product&nbsp;of&nbsp;a&nbsp;pair&nbsp;of&nbsp;complexes.</tt></dd></dl>
<dl><dt><a name="-getComplexDot"><strong>getComplexDot</strong></a>(firstComplex, secondComplex)</dt><dd><tt>Get&nbsp;the&nbsp;dot&nbsp;product&nbsp;of&nbsp;a&nbsp;pair&nbsp;of&nbsp;complexes.</tt></dd></dl>
<dl><dt><a name="-getComplexMaximum"><strong>getComplexMaximum</strong></a>(firstComplex, secondComplex)</dt><dd><tt>Get&nbsp;a&nbsp;complex&nbsp;with&nbsp;each&nbsp;component&nbsp;the&nbsp;maximum&nbsp;of&nbsp;the&nbsp;respective&nbsp;components&nbsp;of&nbsp;a&nbsp;pair&nbsp;of&nbsp;complexes.</tt></dd></dl>
@@ -147,7 +148,9 @@ subtractVec3&nbsp;--&nbsp;Vec3&nbsp;whose&nbsp;angle&nbsp;will&nbsp;be&nbsp;subt
<dl><dt><a name="-getHalfSimplifiedLoop"><strong>getHalfSimplifiedLoop</strong></a>(loop, radius, remainder)</dt><dd><tt>Get&nbsp;the&nbsp;loop&nbsp;with&nbsp;half&nbsp;of&nbsp;the&nbsp;points&nbsp;inside&nbsp;the&nbsp;channel&nbsp;removed.</tt></dd></dl>
<dl><dt><a name="-getHalfSimplifiedPath"><strong>getHalfSimplifiedPath</strong></a>(path, radius, remainder)</dt><dd><tt>Get&nbsp;the&nbsp;path&nbsp;with&nbsp;half&nbsp;of&nbsp;the&nbsp;points&nbsp;inside&nbsp;the&nbsp;channel&nbsp;removed.</tt></dd></dl>
<dl><dt><a name="-getInsidesAddToOutsides"><strong>getInsidesAddToOutsides</strong></a>(loops, outsides)</dt><dd><tt>Add&nbsp;loops&nbsp;to&nbsp;either&nbsp;the&nbsp;insides&nbsp;or&nbsp;outsides.</tt></dd></dl>
+ <dl><dt><a name="-getIntermediateLocation"><strong>getIntermediateLocation</strong></a>(alongWay, begin, end)</dt><dd><tt>Get&nbsp;the&nbsp;intermediate&nbsp;location&nbsp;between&nbsp;begin&nbsp;and&nbsp;end.</tt></dd></dl>
<dl><dt><a name="-getLeftPoint"><strong>getLeftPoint</strong></a>(path)</dt><dd><tt>Get&nbsp;the&nbsp;leftmost&nbsp;point&nbsp;in&nbsp;the&nbsp;path.</tt></dd></dl>
+ <dl><dt><a name="-getLoopStartingNearest"><strong>getLoopStartingNearest</strong></a>(extrusionHalfWidthSquared, location, loop)</dt><dd><tt>Add&nbsp;to&nbsp;threads&nbsp;from&nbsp;the&nbsp;last&nbsp;location&nbsp;from&nbsp;loop.</tt></dd></dl>
<dl><dt><a name="-getMaximumSpan"><strong>getMaximumSpan</strong></a>(loop)</dt><dd><tt>Get&nbsp;the&nbsp;maximum&nbsp;span&nbsp;in&nbsp;the&nbsp;xy&nbsp;plane.</tt></dd></dl>
<dl><dt><a name="-getNearestDistanceSquaredIndex"><strong>getNearestDistanceSquaredIndex</strong></a>(point, loop)</dt><dd><tt>Get&nbsp;the&nbsp;distance&nbsp;squared&nbsp;to&nbsp;the&nbsp;nearest&nbsp;segment&nbsp;of&nbsp;the&nbsp;loop&nbsp;and&nbsp;index&nbsp;of&nbsp;that&nbsp;segment.</tt></dd></dl>
<dl><dt><a name="-getNearestPathDistanceSquaredIndex"><strong>getNearestPathDistanceSquaredIndex</strong></a>(point, path)</dt><dd><tt>Get&nbsp;the&nbsp;distance&nbsp;squared&nbsp;to&nbsp;the&nbsp;nearest&nbsp;segment&nbsp;of&nbsp;the&nbsp;path&nbsp;and&nbsp;index&nbsp;of&nbsp;that&nbsp;segment.</tt></dd></dl>
@@ -211,6 +214,7 @@ vector3&nbsp;-&nbsp;Vec3&nbsp;whose&nbsp;rotation&nbsp;will&nbsp;be&nbsp;returne
<dl><dt><a name="-isInsideOtherLoops"><strong>isInsideOtherLoops</strong></a>(loopIndex, loops)</dt><dd><tt>Determine&nbsp;if&nbsp;a&nbsp;loop&nbsp;in&nbsp;a&nbsp;list&nbsp;is&nbsp;inside&nbsp;another&nbsp;loop&nbsp;in&nbsp;that&nbsp;list.</tt></dd></dl>
<dl><dt><a name="-isLargeSameDirection"><strong>isLargeSameDirection</strong></a>(inset, loop, requiredSize)</dt><dd><tt>Determine&nbsp;if&nbsp;the&nbsp;inset&nbsp;is&nbsp;in&nbsp;the&nbsp;same&nbsp;direction&nbsp;as&nbsp;the&nbsp;loop&nbsp;and&nbsp;if&nbsp;the&nbsp;inset&nbsp;is&nbsp;as&nbsp;large&nbsp;as&nbsp;the&nbsp;required&nbsp;size.</tt></dd></dl>
<dl><dt><a name="-isLineIntersectingInsideXSegment"><strong>isLineIntersectingInsideXSegment</strong></a>(segmentFirstX, segmentSecondX, vector3First, vector3Second, y)</dt><dd><tt>Determine&nbsp;if&nbsp;the&nbsp;line&nbsp;is&nbsp;crossing&nbsp;inside&nbsp;the&nbsp;x&nbsp;segment.</tt></dd></dl>
+ <dl><dt><a name="-isLineIntersectingLoops"><strong>isLineIntersectingLoops</strong></a>(loops, pointBegin, pointEnd)</dt><dd><tt>Determine&nbsp;if&nbsp;the&nbsp;line&nbsp;is&nbsp;intersecting&nbsp;loops.</tt></dd></dl>
<dl><dt><a name="-isLoopIntersectingInsideXSegment"><strong>isLoopIntersectingInsideXSegment</strong></a>(loop, segmentFirstX, segmentSecondX, segmentYMirror, y)</dt><dd><tt>Determine&nbsp;if&nbsp;the&nbsp;loop&nbsp;is&nbsp;intersecting&nbsp;inside&nbsp;the&nbsp;x&nbsp;segment.</tt></dd></dl>
<dl><dt><a name="-isLoopIntersectingLoops"><strong>isLoopIntersectingLoops</strong></a>(loop, otherLoops)</dt><dd><tt>Determine&nbsp;if&nbsp;the&nbsp;loop&nbsp;is&nbsp;intersecting&nbsp;other&nbsp;loops.</tt></dd></dl>
<dl><dt><a name="-isLoopListIntersectingInsideXSegment"><strong>isLoopListIntersectingInsideXSegment</strong></a>(loopList, segmentFirstX, segmentSecondX, segmentYMirror, y)</dt><dd><tt>Determine&nbsp;if&nbsp;the&nbsp;loop&nbsp;list&nbsp;is&nbsp;crossing&nbsp;inside&nbsp;the&nbsp;x&nbsp;segment.</tt></dd></dl>
diff --git a/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.skeinforge_utilities.intercircle.html b/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.skeinforge_utilities.intercircle.html
index 81ed84cc..434444e1 100644
--- a/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.skeinforge_utilities.intercircle.html
+++ b/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.skeinforge_utilities.intercircle.html
@@ -124,6 +124,7 @@
<dl><dt><a name="-getInsetFromClockwiseTriple"><strong>getInsetFromClockwiseTriple</strong></a>(aheadAbsolute, behindAbsolute, center, radius)</dt><dd><tt>Get&nbsp;loop&nbsp;inset&nbsp;from&nbsp;clockwise&nbsp;triple,&nbsp;out&nbsp;from&nbsp;widdershins&nbsp;loop.</tt></dd></dl>
<dl><dt><a name="-getIntersectionAtInset"><strong>getIntersectionAtInset</strong></a>(ahead, behind, inset)</dt><dd><tt>Get&nbsp;circle&nbsp;intersection&nbsp;loop&nbsp;at&nbsp;inset&nbsp;from&nbsp;segment.</tt></dd></dl>
<dl><dt><a name="-getLoopsFromLoopsDirection"><strong>getLoopsFromLoopsDirection</strong></a>(isWiddershins, loops)</dt><dd><tt>Get&nbsp;the&nbsp;loops&nbsp;going&nbsp;round&nbsp;in&nbsp;a&nbsp;given&nbsp;direction.</tt></dd></dl>
+ <dl><dt><a name="-getSimplifiedInsetFromClockwiseLoop"><strong>getSimplifiedInsetFromClockwiseLoop</strong></a>(loop, radius)</dt><dd><tt>Get&nbsp;loop&nbsp;inset&nbsp;from&nbsp;clockwise&nbsp;loop,&nbsp;out&nbsp;from&nbsp;widdershins&nbsp;loop.</tt></dd></dl>
<dl><dt><a name="-getWithoutIntersections"><strong>getWithoutIntersections</strong></a>(loop)</dt><dd><tt>Get&nbsp;loop&nbsp;without&nbsp;intersections.</tt></dd></dl>
<dl><dt><a name="-isLoopIntersectingLoop"><strong>isLoopIntersectingLoop</strong></a>(anotherLoop, loop)</dt><dd><tt>Determine&nbsp;if&nbsp;the&nbsp;a&nbsp;loop&nbsp;is&nbsp;intersecting&nbsp;another&nbsp;loop.</tt></dd></dl>
<dl><dt><a name="-removeIntersection"><strong>removeIntersection</strong></a>(loop)</dt><dd><tt>Get&nbsp;loop&nbsp;without&nbsp;the&nbsp;first&nbsp;intersection.</tt></dd></dl>
diff --git a/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.slice_shape.html b/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.slice_shape.html
index 31a80d25..2ba3c47b 100644
--- a/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.slice_shape.html
+++ b/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.slice_shape.html
@@ -131,7 +131,7 @@ many&nbsp;lines&nbsp;of&nbsp;GNU&nbsp;Triangulated&nbsp;Surface&nbsp;vertices,&n
<dl><dt><a name="SliceSkein-addFromUpperLowerFile"><strong>addFromUpperLowerFile</strong></a>(self, filename)</dt><dd><tt>Add&nbsp;lines&nbsp;of&nbsp;text&nbsp;from&nbsp;the&nbsp;filename&nbsp;or&nbsp;the&nbsp;lowercase&nbsp;filename,&nbsp;if&nbsp;there&nbsp;is&nbsp;no&nbsp;file&nbsp;by&nbsp;the&nbsp;original&nbsp;filename&nbsp;in&nbsp;the&nbsp;directory.</tt></dd></dl>
-<dl><dt><a name="SliceSkein-addGcodeFromPerimeterPaths"><strong>addGcodeFromPerimeterPaths</strong></a>(self, loop, loopLists, radius)</dt><dd><tt>Add&nbsp;the&nbsp;perimeter&nbsp;paths&nbsp;to&nbsp;the&nbsp;output.</tt></dd></dl>
+<dl><dt><a name="SliceSkein-addGcodeFromPerimeterPaths"><strong>addGcodeFromPerimeterPaths</strong></a>(self, isIntersectingSelf, loop, loopLists, radius)</dt><dd><tt>Add&nbsp;the&nbsp;perimeter&nbsp;paths&nbsp;to&nbsp;the&nbsp;output.</tt></dd></dl>
<dl><dt><a name="SliceSkein-addGcodeFromRemainingLoop"><strong>addGcodeFromRemainingLoop</strong></a>(self, loop, loopLists, radius)</dt><dd><tt>Add&nbsp;the&nbsp;remainder&nbsp;of&nbsp;the&nbsp;loop&nbsp;which&nbsp;does&nbsp;not&nbsp;overlap&nbsp;the&nbsp;alreadyFilledArounds&nbsp;loops.</tt></dd></dl>
@@ -169,6 +169,7 @@ many&nbsp;lines&nbsp;of&nbsp;GNU&nbsp;Triangulated&nbsp;Surface&nbsp;vertices,&n
<td width="100%"><dl><dt><a name="-addAlreadyFilledArounds"><strong>addAlreadyFilledArounds</strong></a>(alreadyFilledArounds, loop, radius)</dt><dd><tt>Add&nbsp;already&nbsp;filled&nbsp;loops&nbsp;around&nbsp;loop&nbsp;to&nbsp;alreadyFilledArounds.</tt></dd></dl>
<dl><dt><a name="-addEdgePair"><strong>addEdgePair</strong></a>(edgePairTable, edges, faceEdgeIndex, remainingEdgeIndex, remainingEdgeTable)</dt><dd><tt>Add&nbsp;edge&nbsp;pair&nbsp;to&nbsp;the&nbsp;edge&nbsp;pair&nbsp;table.</tt></dd></dl>
<dl><dt><a name="-addPointsAtZ"><strong>addPointsAtZ</strong></a>(edgePair, points, radius, vertices, z)</dt><dd><tt>Add&nbsp;points&nbsp;on&nbsp;the&nbsp;segment&nbsp;between&nbsp;the&nbsp;edge&nbsp;intersections&nbsp;with&nbsp;z.</tt></dd></dl>
+ <dl><dt><a name="-addSegmentOutline"><strong>addSegmentOutline</strong></a>(isThick, outlines, pointBegin, pointEnd, width)</dt><dd><tt>Add&nbsp;a&nbsp;diamond&nbsp;or&nbsp;hexagonal&nbsp;outline&nbsp;for&nbsp;a&nbsp;line&nbsp;segment.</tt></dd></dl>
<dl><dt><a name="-getCommonVertexIndex"><strong>getCommonVertexIndex</strong></a>(edgeFirst, edgeSecond)</dt><dd><tt>Get&nbsp;the&nbsp;vertex&nbsp;index&nbsp;that&nbsp;both&nbsp;edges&nbsp;have&nbsp;in&nbsp;common.</tt></dd></dl>
<dl><dt><a name="-getDoubledRoundZ"><strong>getDoubledRoundZ</strong></a>(overhangingSegment, segmentRoundZ)</dt><dd><tt>Get&nbsp;doubled&nbsp;plane&nbsp;angle&nbsp;around&nbsp;z&nbsp;of&nbsp;the&nbsp;overhanging&nbsp;segment.</tt></dd></dl>
<dl><dt><a name="-getLoopsFromCorrectMesh"><strong>getLoopsFromCorrectMesh</strong></a>(edges, faces, vertices, z)</dt><dd><tt>Get&nbsp;loops&nbsp;from&nbsp;a&nbsp;slice&nbsp;of&nbsp;a&nbsp;correct&nbsp;mesh.</tt></dd></dl>
@@ -179,11 +180,12 @@ many&nbsp;lines&nbsp;of&nbsp;GNU&nbsp;Triangulated&nbsp;Surface&nbsp;vertices,&n
<dl><dt><a name="-getPath"><strong>getPath</strong></a>(edges, pathIndexes, loop, z)</dt><dd><tt>Get&nbsp;the&nbsp;path&nbsp;from&nbsp;the&nbsp;edge&nbsp;intersections.</tt></dd></dl>
<dl><dt><a name="-getPathIndexesAddPath"><strong>getPathIndexesAddPath</strong></a>(edges, faces, loops, remainingEdgeTable, vertices, z)</dt><dd><tt>Get&nbsp;the&nbsp;path&nbsp;indexes&nbsp;around&nbsp;a&nbsp;triangle&nbsp;mesh&nbsp;slice&nbsp;and&nbsp;add&nbsp;the&nbsp;path&nbsp;to&nbsp;the&nbsp;loops.</tt></dd></dl>
<dl><dt><a name="-getRemainingEdgeTable"><strong>getRemainingEdgeTable</strong></a>(edges, vertices, z)</dt><dd><tt>Get&nbsp;the&nbsp;remaining&nbsp;edge&nbsp;hashtable.</tt></dd></dl>
- <dl><dt><a name="-getSegmentsFromPoints"><strong>getSegmentsFromPoints</strong></a>(loopLists, pointBegin, pointEnd)</dt><dd><tt>Get&nbsp;enpoint&nbsp;segments&nbsp;from&nbsp;the&nbsp;beginning&nbsp;and&nbsp;end&nbsp;of&nbsp;a&nbsp;line&nbsp;segment.</tt></dd></dl>
+ <dl><dt><a name="-getSegmentsFromPoints"><strong>getSegmentsFromPoints</strong></a>(loopLists, pointBegin, pointEnd)</dt><dd><tt>Get&nbsp;endpoint&nbsp;segments&nbsp;from&nbsp;the&nbsp;beginning&nbsp;and&nbsp;end&nbsp;of&nbsp;a&nbsp;line&nbsp;segment.</tt></dd></dl>
<dl><dt><a name="-getSharedFace"><strong>getSharedFace</strong></a>(firstEdge, faces, secondEdge)</dt><dd><tt>Get&nbsp;the&nbsp;face&nbsp;which&nbsp;is&nbsp;shared&nbsp;by&nbsp;two&nbsp;edges.</tt></dd></dl>
<dl><dt><a name="-getSliceGcode"><strong>getSliceGcode</strong></a>(filename, slicePreferences<font color="#909090">=None</font>)</dt><dd><tt>Slice&nbsp;a&nbsp;shape&nbsp;file.</tt></dd></dl>
<dl><dt><a name="-getSliceIntersectionFromEdge"><strong>getSliceIntersectionFromEdge</strong></a>(edge, loop, z)</dt><dd><tt>Get&nbsp;the&nbsp;point&nbsp;where&nbsp;the&nbsp;slice&nbsp;intersects&nbsp;the&nbsp;edge.</tt></dd></dl>
<dl><dt><a name="-isCloseToLast"><strong>isCloseToLast</strong></a>(paths, point, radius)</dt><dd><tt>Determine&nbsp;if&nbsp;the&nbsp;point&nbsp;is&nbsp;close&nbsp;to&nbsp;the&nbsp;last&nbsp;point&nbsp;of&nbsp;the&nbsp;last&nbsp;path.</tt></dd></dl>
+ <dl><dt><a name="-isIntersectingItself"><strong>isIntersectingItself</strong></a>(loop, width)</dt><dd><tt>Determine&nbsp;if&nbsp;the&nbsp;loop&nbsp;is&nbsp;intersecting&nbsp;itself.</tt></dd></dl>
<dl><dt><a name="-isIntersectingWithinList"><strong>isIntersectingWithinList</strong></a>(loop, loopList)</dt><dd><tt>Determine&nbsp;if&nbsp;the&nbsp;loop&nbsp;is&nbsp;intersecting&nbsp;or&nbsp;is&nbsp;within&nbsp;the&nbsp;loop&nbsp;list.</tt></dd></dl>
<dl><dt><a name="-isIntersectingWithinLists"><strong>isIntersectingWithinLists</strong></a>(loop, loopLists)</dt><dd><tt>Determine&nbsp;if&nbsp;the&nbsp;loop&nbsp;is&nbsp;intersecting&nbsp;or&nbsp;is&nbsp;within&nbsp;the&nbsp;loop&nbsp;lists.</tt></dd></dl>
<dl><dt><a name="-isZInEdge"><strong>isZInEdge</strong></a>(edge, vertices, z)</dt><dd><tt>Determine&nbsp;if&nbsp;z&nbsp;is&nbsp;inside&nbsp;the&nbsp;edge.</tt></dd></dl>
diff --git a/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.tower.html b/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.tower.html
index 18742595..b47de3b0 100644
--- a/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.tower.html
+++ b/trunk/reprap/miscellaneous/python-beanshell-scripts/documentation/skeinforge_tools.tower.html
@@ -36,7 +36,9 @@ The&nbsp;following&nbsp;examples&nbsp;tower&nbsp;the&nbsp;files&nbsp;Hollow&nbsp
which&nbsp;contains&nbsp;Hollow&nbsp;Square.gcode,&nbsp;Hollow&nbsp;Square.gts&nbsp;and&nbsp;tower.py.&nbsp;&nbsp;The&nbsp;tower&nbsp;function&nbsp;will&nbsp;tower&nbsp;if&nbsp;'Maximum&nbsp;Tower&nbsp;Layers'&nbsp;is<br>
greater&nbsp;than&nbsp;zero,&nbsp;which&nbsp;can&nbsp;be&nbsp;set&nbsp;in&nbsp;the&nbsp;dialog&nbsp;or&nbsp;by&nbsp;changing&nbsp;the&nbsp;preferences&nbsp;file&nbsp;'tower.csv'&nbsp;with&nbsp;a&nbsp;text&nbsp;editor&nbsp;or&nbsp;a&nbsp;spreadsheet<br>
program&nbsp;set&nbsp;to&nbsp;separate&nbsp;tabs.&nbsp;&nbsp;The&nbsp;functions&nbsp;writeOutput&nbsp;and&nbsp;getTowerChainGcode&nbsp;check&nbsp;to&nbsp;see&nbsp;if&nbsp;the&nbsp;text&nbsp;has&nbsp;been&nbsp;towered,<br>
-if&nbsp;not&nbsp;they&nbsp;call&nbsp;the&nbsp;getFillChainGcode&nbsp;in&nbsp;fill.py&nbsp;to&nbsp;fill&nbsp;the&nbsp;text;&nbsp;once&nbsp;they&nbsp;have&nbsp;the&nbsp;filled&nbsp;text,&nbsp;then&nbsp;they&nbsp;tower.<br>
+if&nbsp;not&nbsp;they&nbsp;call&nbsp;the&nbsp;getFillChainGcode&nbsp;in&nbsp;fill.py&nbsp;to&nbsp;fill&nbsp;the&nbsp;text;&nbsp;once&nbsp;they&nbsp;have&nbsp;the&nbsp;filled&nbsp;text,&nbsp;then&nbsp;they&nbsp;tower.&nbsp;&nbsp;Pictures&nbsp;of&nbsp;towering&nbsp;in<br>
+action&nbsp;are&nbsp;available&nbsp;from&nbsp;the&nbsp;Metalab&nbsp;blog&nbsp;at:<br>
+<a href="http://reprap.soup.io/?search=towering">http://reprap.soup.io/?search=towering</a><br>
&nbsp;<br>
&nbsp;<br>
&gt;&nbsp;python&nbsp;tower.py<br>
diff --git a/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge.py b/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge.py
index 81fdfcb5..5132c591 100644
--- a/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge.py
+++ b/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge.py
@@ -163,6 +163,12 @@ https://reprap.svn.sourceforge.net/svnroot/reprap/trunk/reprap/miscellaneous/pyt
+Motto
+
+I may be slow, but I get there in the end.
+
+
+
Troubleshooting
You can ask for skeinforge help by posting in the "How to Print Gcode from Host" thread at:
@@ -235,7 +241,7 @@ def getSkeinforgeToolFilenames():
def writeOutput( filename = '' ):
"Skeinforge a gcode file. If no filename is specified, skeinforge the first gcode file in this folder that is not modified."
skeinforgePluginFilenames = getSkeinforgeToolFilenames()
- toolNames = 'export fillet oozebane nozzle_wipe hop stretch raft comb tower fill slice_shape'.split()
+ toolNames = 'export fillet oozebane nozzle_wipe hop stretch raft clip comb tower fill slice_shape'.split()
for toolName in toolNames:
for skeinforgePluginFilename in skeinforgePluginFilenames:
if skeinforgePluginFilename == toolName:
diff --git a/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/analyze_plugins/skeinview.py b/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/analyze_plugins/skeinview.py
index bd66d424..0463a6a8 100644
--- a/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/analyze_plugins/skeinview.py
+++ b/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/analyze_plugins/skeinview.py
@@ -153,8 +153,8 @@ class SkeinviewSkein:
"Add a point to travel and maybe extrusion."
if self.oldLocation == None:
return
- beginningComplex = self.oldLocation.dropAxis( 2 )
- endComplex = location.dropAxis( 2 )
+ beginningComplex = complex( self.oldLocation.x, self.cornerImaginaryTotal - self.oldLocation.y )
+ endComplex = complex( location.x, self.cornerImaginaryTotal - location.y )
colorName = 'gray'
if self.extruderActive:
colorName = self.colorNames[ self.extrusionNumber % len( self.colorNames ) ]
@@ -218,6 +218,7 @@ class SkeinviewSkein:
self.scale = skeinviewPreferences.pixelsWidthExtrusion.value / self.extrusionWidth
self.scaleCornerHigh = self.scale * self.cornerHigh.dropAxis( 2 )
self.scaleCornerLow = self.scale * self.cornerLow.dropAxis( 2 )
+ self.cornerImaginaryTotal = self.cornerHigh.y + self.cornerLow.y
margin = complex( 5.0, 5.0 )
self.marginCornerLow = self.scaleCornerLow - margin
self.scaleSize = margin + self.scaleCornerHigh - self.marginCornerLow
diff --git a/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/analyze_plugins/vectorwrite.py b/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/analyze_plugins/vectorwrite.py
index 86a8ffda..0bd76937 100644
--- a/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/analyze_plugins/vectorwrite.py
+++ b/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/analyze_plugins/vectorwrite.py
@@ -85,6 +85,7 @@ def writeVectorFileGivenText( filename, gcodeText, vectorwritePreferences ):
skein.parseGcode( gcodeText, vectorwritePreferences )
print( 'The scalable vector graphics file is saved as ' + skein.getFilenameWriteFiles( filename ) )
+
class VectorWindow:
"A class to accumulate a scalable vector graphics text."
def __init__( self ):
@@ -145,6 +146,28 @@ class VectorWindow:
self.width = int( self.topRightCorner.real - self.bottomLeftCorner.real )
+class VectorwritePreferences:
+ "A class to handle the vectorwrite preferences."
+ def __init__( self ):
+ "Set the default preferences, execute title & preferences filename."
+ #Set the default preferences.
+ self.archive = []
+ self.activateVectorwrite = preferences.BooleanPreference().getFromValue( 'Activate Vectorwrite', False )
+ self.archive.append( self.activateVectorwrite )
+ self.filenameInput = preferences.Filename().getFromFilename( [ ( 'Gcode text files', '*.gcode' ) ], 'Open File to Write Vector Graphics for', '' )
+ self.archive.append( self.filenameInput )
+ self.minimumNumberLayersMultipleFiles = preferences.IntPreference().getFromValue( 'Minimum Number of Layers for Multiple Files (integer):', 10 )
+ self.archive.append( self.minimumNumberLayersMultipleFiles )
+ self.pixelsWidthExtrusion = preferences.FloatPreference().getFromValue( 'Pixels over Extrusion Width (ratio):', 5.0 )
+ self.archive.append( self.pixelsWidthExtrusion )
+ #Create the archive, title of the execute button, title of the dialog & preferences filename.
+ self.executeTitle = 'Write Vector Graphics'
+ self.filenamePreferences = preferences.getPreferencesFilePath( 'vectorwrite.csv' )
+ self.filenameHelp = 'skeinforge_tools.analyze_plugins.vectorwrite.html'
+ self.saveTitle = 'Save Preferences'
+ self.title = 'Vectorwrite Preferences'
+
+
class VectorwriteSkein:
"A class to write a get a scalable vector graphics text for a gcode skein."
def __init__( self ):
@@ -336,28 +359,6 @@ class VectorwriteSkein:
hypertext.write( '</body>\n</html>' )
gcodec.writeFileText( htmlPageFilename, hypertext.getvalue() )
-
-class VectorwritePreferences:
- "A class to handle the vectorwrite preferences."
- def __init__( self ):
- "Set the default preferences, execute title & preferences filename."
- #Set the default preferences.
- self.archive = []
- self.activateVectorwrite = preferences.BooleanPreference().getFromValue( 'Activate Vectorwrite', False )
- self.archive.append( self.activateVectorwrite )
- self.filenameInput = preferences.Filename().getFromFilename( [ ( 'Gcode text files', '*.gcode' ) ], 'Open File to Write Vector Graphics for', '' )
- self.archive.append( self.filenameInput )
- self.minimumNumberLayersMultipleFiles = preferences.IntPreference().getFromValue( 'Minimum Number of Layers for Multiple Files (integer):', 10 )
- self.archive.append( self.minimumNumberLayersMultipleFiles )
- self.pixelsWidthExtrusion = preferences.FloatPreference().getFromValue( 'Pixels over Extrusion Width (ratio):', 10.0 )
- self.archive.append( self.pixelsWidthExtrusion )
- #Create the archive, title of the execute button, title of the dialog & preferences filename.
- self.executeTitle = 'Write Vector Graphics'
- self.filenamePreferences = preferences.getPreferencesFilePath( 'vectorwrite.csv' )
- self.filenameHelp = 'skeinforge_tools.analyze_plugins.vectorwrite.html'
- self.saveTitle = 'Save Preferences'
- self.title = 'Vectorwrite Preferences'
-
def execute( self ):
"Write button has been clicked."
filenames = polyfile.getFileOrGcodeDirectory( self.filenameInput.value, self.filenameInput.wasCancelled )
diff --git a/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/comb.py b/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/comb.py
index cef89281..42bba481 100644
--- a/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/comb.py
+++ b/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/comb.py
@@ -1,9 +1,13 @@
"""
Comb is a script to comb the extrusion hair of a gcode file.
-Comb bends the extruder travel paths around holes in the slice, to avoid stringers. The default 'Activate Comb' checkbox is on.
-When it's on the paths are bent. When it is off, this script does nothing, the gcode text is handed over the next tool in the
-skeinforge chain. To run comb, in a shell type:
+The default 'Activate Comb' checkbox is on. When it is on, the functions described below will work, when it is off, the functions
+will not be called.
+
+Comb bends the extruder travel paths around holes in the slice, to avoid stringers and it jitters the loop end position to a different
+place on each layer to prevent the a ridge from forming. The "Jitter Over Extrusion Width (ratio)" is the ratio of the amount the
+loop ends will be jittered. A high value means the loops will start all over the place and a low value means loops will start at
+roughly the same place on each layer. To run comb, in a shell type:
> python comb.py
The following examples comb the files Hollow Square.gcode & Hollow Square.gts. The examples are run in a terminal in the folder
@@ -11,7 +15,8 @@ which contains Hollow Square.gcode, Hollow Square.gts and comb.py. The comb fun
can be set in the dialog or by changing the preferences file 'comb.csv' in the '.skeinforge' folder in your home directory with a text
editor or a spreadsheet program set to separate tabs. The functions writeOutput and getCombChainGcode check to see if the
text has been combed, if not they call getTowerChainGcode in tower.py to tower the text; once they have the towered text, then
-they comb.
+they comb. Pictures of combing in action are available from the Metalab blog at:
+http://reprap.soup.io/?search=combing
> python comb.py
@@ -68,6 +73,7 @@ from skeinforge_tools import import_translator
from skeinforge_tools import polyfile
from skeinforge_tools import tower
import cStringIO
+import math
import sys
import time
@@ -96,7 +102,7 @@ def getCombGcode( gcodeText, combPreferences = None ):
if not combPreferences.activateComb.value:
return gcodeText
skein = CombSkein()
- skein.parseGcode( gcodeText )
+ skein.parseGcode( combPreferences, gcodeText )
return skein.output.getvalue()
def isLoopNumberEqual( betweenX, betweenXIndex, loopNumber ):
@@ -126,42 +132,121 @@ def writeOutput( filename = '' ):
analyze.writeOutput( suffixFilename, combGcode )
print( 'It took ' + str( int( round( time.time() - startTime ) ) ) + ' seconds to comb the file.' )
+
+class CombPreferences:
+ "A class to handle the comb preferences."
+ def __init__( self ):
+ "Set the default preferences, execute title & preferences filename."
+ #Set the default preferences.
+ self.archive = []
+ self.activateComb = preferences.BooleanPreference().getFromValue( 'Activate Comb', True )
+ self.archive.append( self.activateComb )
+ self.arrivalInsetFollowDistanceOverExtrusionWidth = preferences.FloatPreference().getFromValue( 'Arrival Inset Follow Distance over Extrusion Width (ratio):', 3.0 )
+ self.archive.append( self.arrivalInsetFollowDistanceOverExtrusionWidth )
+ self.filenameInput = preferences.Filename().getFromFilename( import_translator.getGNUTranslatorGcodeFileTypeTuples(), 'Open File to be Combed', '' )
+ self.archive.append( self.filenameInput )
+ #Create the archive, title of the execute button, title of the dialog & preferences filename.
+ self.jitterOverExtrusionWidth = preferences.FloatPreference().getFromValue( 'Jitter Over Extrusion Width (ratio):', 2.0 )
+ self.archive.append( self.jitterOverExtrusionWidth )
+ self.executeTitle = 'Comb'
+ self.filenamePreferences = preferences.getPreferencesFilePath( 'comb.csv' )
+ self.filenameHelp = 'skeinforge_tools.comb.html'
+ self.saveTitle = 'Save Preferences'
+ self.title = 'Comb Preferences'
+
+ def execute( self ):
+ "Comb button has been clicked."
+ filenames = polyfile.getFileOrDirectoryTypesUnmodifiedGcode( self.filenameInput.value, import_translator.getGNUTranslatorFileTypes(), self.filenameInput.wasCancelled )
+ for filename in filenames:
+ writeOutput( filename )
+
+
class CombSkein:
"A class to comb a skein of extrusions."
def __init__( self ):
+ self.beforeLoopLocation = None
self.betweenTable = {}
+ self.boundaryLoop = None
self.bridgeExtrusionWidthOverSolid = 1.0
- self.decimalPlacesCarried = 3
- self.extruderActive = False
self.fillInset = 0.18
+ self.isPerimeter = False
self.layerFillInset = self.fillInset
self.layer = None
self.layers = []
self.layerTable = {}
self.layerZ = None
+ self.lineIndex = 0
self.lines = None
- self.loop = None
- self.oldLocation = None
self.oldZ = None
- self.output = cStringIO.StringIO()
+ self.perimeter = None
self.pointTable = {}
+ self.initializeMoreParameters()
+
+ def addGcodeFromThread( self, thread ):
+ "Add a gcode thread to the output."
+ if len( thread ) > 0:
+ self.addGcodeMovement( thread[ 0 ] )
+ else:
+ print( "zero length vertex positions array which was skipped over, this should never happen" )
+ if len( thread ) < 2:
+ return
+ self.addLine( 'M101' )
+ for point in thread[ 1 : ]:
+ self.addGcodeMovement( point )
def addGcodeMovement( self, point ):
"Add a movement to the output."
- self.addLine( "G1 X%s Y%s Z%s" % ( self.getRounded( point.x ), self.getRounded( point.y ), self.getRounded( point.z ) ) )
+ if self.feedrateMinute == None:
+ self.addLine( "G1 X%s Y%s Z%s" % ( self.getRounded( point.x ), self.getRounded( point.y ), self.getRounded( point.z ) ) )
+ else:
+ self.addLine( "G1 X%s Y%s Z%s F%s" % ( self.getRounded( point.x ), self.getRounded( point.y ), self.getRounded( point.z ), self.getRounded( self.feedrateMinute ) ) )
def addIfTravel( self, splitLine ):
"Add travel move around loops if this the extruder is off."
location = gcodec.getLocationFromSplitLine( self.oldLocation, splitLine )
if not self.extruderActive and self.oldLocation != None:
if len( self.getBetweens() ) > 0:
- self.insertPathsBetween( self.getOutloopLocation( location ), self.getOutloopLocation( self.oldLocation ) )
+ self.insertPathsAroundBetween( location )
self.oldLocation = location
def addLine( self, line ):
"Add a line of text and a newline to the output."
self.output.write( line + "\n" )
+ def addPathBeforeEnd( self, loop ):
+ "Add the path before the end of the loop."
+ halfFillInset = 0.5 * self.layerFillInset
+ if self.arrivalInsetFollowDistance < halfFillInset:
+ return
+ beginningPoint = loop[ 0 ]
+ closestInset = None
+ closestDistanceSquaredIndex = complex( 999999999999999999.0, - 1 )
+ circleNodes = intercircle.getCircleNodesFromLoop( loop, self.layerFillInset )
+ centers = intercircle.getCentersFromCircleNodes( circleNodes )
+ for center in centers:
+ inset = intercircle.getInsetFromClockwiseLoop( center, halfFillInset )
+ if euclidean.isLargeSameDirection( inset, center, self.layerFillInset ):
+ if euclidean.isPathInsideLoop( loop, inset ) == euclidean.isWiddershins( loop ):
+ distanceSquaredIndex = euclidean.getNearestDistanceSquaredIndex( beginningPoint, inset )
+ if distanceSquaredIndex.real < closestDistanceSquaredIndex.real:
+ closestInset = inset
+ closestDistanceSquaredIndex = distanceSquaredIndex
+ if closestInset == None:
+ return
+ if euclidean.getPolygonLength( closestInset ) < 0.2 * self.arrivalInsetFollowDistance:
+ return
+ closestInset.append( closestInset[ 0 ] )
+ closestInset.reverse()
+ pathBeforeArrival = euclidean.getClippedLoopPath( self.arrivalInsetFollowDistance, closestInset )
+ pointBeforeArrival = pathBeforeArrival[ - 1 ]
+ self.addGcodeMovement( pointBeforeArrival )
+ if self.arrivalInsetFollowDistance <= halfFillInset:
+ return
+ pathBetween = euclidean.getClippedLoopPath( halfFillInset, closestInset )[ len( pathBeforeArrival ) - 1 : ]
+ for point in pathBetween:
+ if not self.isClose( pointBeforeArrival, point ):
+ self.addGcodeMovement( point )
+
def addPathBetween( self, betweenFirst, betweenSecond, loopFirst ):
"Add a path between the perimeter and the fill."
clockwisePath = [ betweenFirst ]
@@ -183,18 +268,30 @@ class CombSkein:
for point in widdershinsPath:
self.addGcodeMovement( point )
+ def addTailoredLoopPath( self ):
+ "Add a clipped and jittered loop path."
+ loop = self.loopPath[ : - 1 ]
+ jitterDistance = self.layerJitter + self.arrivalInsetFollowDistance
+ if self.beforeLoopLocation != None:
+ extrusionHalfWidthSquared = 0.25 * self.extrusionWidth * self.extrusionWidth
+ loop = euclidean.getLoopStartingNearest( extrusionHalfWidthSquared, self.beforeLoopLocation, loop )
+ if jitterDistance != 0.0:
+ loop = self.getJitteredLoop( jitterDistance, loop )
+ self.loopPath = loop + [ loop[ 0 ] ]
+ self.addGcodeFromThread( self.loopPath )
+ self.loopPath = None
+
def addToLoop( self, location ):
"Add a location to loop."
if self.layer == None:
if not self.oldZ in self.layerTable:
self.layerTable[ self.oldZ ] = []
self.layer = self.layerTable[ self.oldZ ]
- if self.loop == None:
- self.loop = [] #starting with an empty array because a closed loop does not have to restate its beginning
- self.layer.append( self.loop )
- if self.loop != None:
- self.loop.append( location )
- self.pointTable[ str( location ) ] = True
+ if self.boundaryLoop == None:
+ self.boundaryLoop = [] #starting with an empty array because a closed loop does not have to restate its beginning
+ self.layer.append( self.boundaryLoop )
+ if self.boundaryLoop != None:
+ self.boundaryLoop.append( location )
def getBetweens( self ):
"Set betweens for the layer."
@@ -202,17 +299,43 @@ class CombSkein:
return self.betweenTable[ self.layerZ ]
halfFillInset = 0.5 * self.layerFillInset
betweens = []
- for loop in self.layerTable[ self.layerZ ]:
- circleNodes = intercircle.getCircleNodesFromLoop( loop, self.layerFillInset )
+ for boundaryLoop in self.layerTable[ self.layerZ ]:
+ circleNodes = intercircle.getCircleNodesFromLoop( boundaryLoop, self.layerFillInset )
centers = intercircle.getCentersFromCircleNodes( circleNodes )
for center in centers:
- inset = intercircle.getInsetFromClockwiseLoop( center, halfFillInset )
+ inset = intercircle.getSimplifiedInsetFromClockwiseLoop( center, halfFillInset )
if euclidean.isLargeSameDirection( inset, center, self.layerFillInset ):
- if euclidean.isPathInsideLoop( loop, inset ) != euclidean.isWiddershins( loop ):
+ if euclidean.isPathInsideLoop( boundaryLoop, inset ) == euclidean.isWiddershins( boundaryLoop ):
betweens.append( inset )
self.betweenTable[ self.layerZ ] = betweens
return betweens
+ def getJitteredLoop( self, jitterDistance, jitterLoop ):
+ "Get a jittered loop path."
+ loopLength = euclidean.getPolygonLength( jitterLoop )
+ lastLength = 0.0
+ pointIndex = 0
+ totalLength = 0.0
+ jitterPosition = ( jitterDistance + 256.0 * loopLength ) % loopLength
+ while totalLength < jitterPosition and pointIndex < len( jitterLoop ):
+ firstPoint = jitterLoop[ pointIndex ]
+ secondPoint = jitterLoop[ ( pointIndex + 1 ) % len( jitterLoop ) ]
+ pointIndex += 1
+ lastLength = totalLength
+ totalLength += firstPoint.distance( secondPoint )
+ remainingLength = jitterPosition - lastLength
+ pointIndex = pointIndex % len( jitterLoop )
+ ultimateJitteredPoint = jitterLoop[ pointIndex ]
+ penultimateJitteredPointIndex = ( pointIndex + len( jitterLoop ) - 1 ) % len( jitterLoop )
+ penultimateJitteredPoint = jitterLoop[ penultimateJitteredPointIndex ]
+ segment = ultimateJitteredPoint.minus( penultimateJitteredPoint )
+ segmentLength = segment.length()
+ originalOffsetLoop = euclidean.getAroundLoop( pointIndex, pointIndex, jitterLoop )
+ if segmentLength <= 0.0:
+ return [ penultimateJitteredPoint ] + originalOffsetLoop[ - 1 ]
+ newUltimatePoint = penultimateJitteredPoint.plus( segment.times( remainingLength / segmentLength ) )
+ return [ newUltimatePoint ] + originalOffsetLoop
+
def getOutloopLocation( self, point ):
"Get location outside of loop."
if str( point ) not in self.pointTable:
@@ -242,6 +365,29 @@ class CombSkein:
"Get number rounded to the number of carried decimal places as a string."
return euclidean.getRoundedToDecimalPlaces( self.decimalPlacesCarried, number )
+ def initializeMoreParameters( self ):
+ "Add a movement to the output."
+ self.extruderActive = False
+ self.feedrateMinute = None
+ self.isLoopPerimeter = False
+ self.layerGolden = 0.0
+ self.loopPath = None
+ self.oldLocation = None
+ self.output = cStringIO.StringIO()
+
+ def insertPathsAroundBetween( self, location ):
+ "Insert paths around and between the perimeter and the fill."
+ outerPerimeter = None
+ if str( location ) in self.pointTable:
+ perimeter = self.pointTable[ str( location ) ]
+ if euclidean.isWiddershins( perimeter ):
+ outerPerimeter = perimeter
+ nextBeginning = self.getOutloopLocation( location )
+ pathEnd = self.getOutloopLocation( self.oldLocation )
+ self.insertPathsBetween( nextBeginning, pathEnd )
+ if outerPerimeter != None:
+ self.addPathBeforeEnd( outerPerimeter )
+
def insertPathsBetween( self, nextBeginning, pathEnd ):
"Insert paths between the perimeter and the fill."
betweenX = []
@@ -276,37 +422,55 @@ class CombSkein:
self.addPathBetween( betweenFirst, betweenSecond, loopFirst )
betweenXIndex += 1
- def parseGcode( self, gcodeText ):
- "Parse gcode text and store the comb gcode."
- self.lines = gcodec.getTextLines( gcodeText )
- for line in self.lines:
- self.parseLine( line )
- self.oldLocation = None
- for lineIndex in range( len( self.lines ) ):
- line = self.lines[ lineIndex ]
- self.parseAddTravel( line )
+ def isClose( self, locationFirst, locationSecond ):
+ "Determine if the first location is close to the second location."
+ return locationFirst.distance2( locationSecond ) < self.closeSquared
- def parseLine( self, line ):
- "Parse a gcode line."
+ def isNextExtruderOn( self ):
+ "Determine if there is an extruder on command before a move command."
+ line = self.lines[ self.lineIndex ]
+ splitLine = line.split()
+ for afterIndex in xrange( self.lineIndex + 1, len( self.lines ) ):
+ line = self.lines[ afterIndex ]
+ splitLine = line.split()
+ firstWord = gcodec.getFirstWord( splitLine )
+ if firstWord == 'G1' or firstWord == 'M103':
+ return False
+ elif firstWord == 'M101':
+ return True
+ return False
+
+ def linearMove( self, splitLine ):
+ "Add to loop path if this is a loop or path."
+ location = gcodec.getLocationFromSplitLine( self.oldLocation, splitLine )
+ self.feedrateMinute = gcodec.getFeedrateMinute( self.feedrateMinute, splitLine )
+ if self.isLoopPerimeter:
+ if self.isNextExtruderOn():
+ self.loopPath = []
+ self.beforeLoopLocation = self.oldLocation
+ if self.loopPath != None:
+ self.loopPath.append( location )
+ self.oldLocation = location
+
+ def parseAddJitter( self, line ):
+ "Parse a gcode line, jitter it and add it to the comb skein."
splitLine = line.split()
if len( splitLine ) < 1:
return
firstWord = splitLine[ 0 ]
- if firstWord == 'M103':
- self.loop = None
- elif firstWord == '(<bridgeExtrusionWidthOverSolid>':
- self.bridgeExtrusionWidthOverSolid = float( splitLine[ 1 ] )
- elif firstWord == '(<boundaryPoint>':
- location = gcodec.getLocationFromSplitLine( None, splitLine )
- self.addToLoop( location )
- elif firstWord == '(<decimalPlacesCarried>':
- self.decimalPlacesCarried = int( splitLine[ 1 ] )
+ if firstWord == 'G1':
+ self.linearMove( splitLine )
+ elif firstWord == 'M103':
+ self.isLoopPerimeter = False
+ if self.loopPath != None:
+ self.addTailoredLoopPath()
elif firstWord == '(<layerStart>':
- self.layer = None
- self.loop = None
- self.oldZ = float( splitLine[ 1 ] )
- elif firstWord == '(<fillInset>':
- self.fillInset = float( splitLine[ 1 ] )
+ self.layerGolden += 0.61803398874989479
+ self.layerJitter = self.jitter * ( math.fmod( self.layerGolden, 1.0 ) - 0.5 )
+ elif firstWord == '(<loop>' or firstWord == '(<perimeter>':
+ self.isLoopPerimeter = True
+ if self.loopPath == None:
+ self.addLine( line )
def parseAddTravel( self, line ):
"Parse a gcode line and add it to the comb skein."
@@ -320,38 +484,82 @@ class CombSkein:
self.extruderActive = True
elif firstWord == 'M103':
self.extruderActive = False
- elif firstWord == '(<extrusionStart>':
- self.addLine( '(<procedureDone> comb )' )
+ elif firstWord == '(<bridgeLayer>':
+ self.layerFillInset = self.fillInset * self.bridgeExtrusionWidthOverSolid
elif firstWord == '(<layerStart>':
self.layerFillInset = self.fillInset
self.layerZ = float( splitLine[ 1 ] )
- elif firstWord == '(<bridgeLayer>':
- self.layerFillInset = self.fillInset * self.bridgeExtrusionWidthOverSolid
self.addLine( line )
+ def parseGcode( self, combPreferences, gcodeText ):
+ "Parse gcode text and store the comb gcode."
+ self.lines = gcodec.getTextLines( gcodeText )
+ self.parseInitialization( combPreferences )
+ for self.lineIndex in xrange( self.lineIndex, len( self.lines ) ):
+ line = self.lines[ self.lineIndex ]
+ self.parseAddJitter( line )
+ self.lines = gcodec.getTextLines( self.output.getvalue() )
+ self.initializeMoreParameters()
+ for self.lineIndex in xrange( len( self.lines ) ):
+ line = self.lines[ self.lineIndex ]
+ self.parseLine( combPreferences, line )
+ for self.lineIndex in xrange( len( self.lines ) ):
+ line = self.lines[ self.lineIndex ]
+ self.parseAddTravel( line )
-class CombPreferences:
- "A class to handle the comb preferences."
- def __init__( self ):
- "Set the default preferences, execute title & preferences filename."
- #Set the default preferences.
- self.archive = []
- self.activateComb = preferences.BooleanPreference().getFromValue( 'Activate Comb', True )
- self.archive.append( self.activateComb )
- self.filenameInput = preferences.Filename().getFromFilename( import_translator.getGNUTranslatorGcodeFileTypeTuples(), 'Open File to be Combed', '' )
- self.archive.append( self.filenameInput )
- #Create the archive, title of the execute button, title of the dialog & preferences filename.
- self.executeTitle = 'Comb'
- self.filenamePreferences = preferences.getPreferencesFilePath( 'comb.csv' )
- self.filenameHelp = 'skeinforge_tools.comb.html'
- self.saveTitle = 'Save Preferences'
- self.title = 'Comb Preferences'
-
- def execute( self ):
- "Comb button has been clicked."
- filenames = polyfile.getFileOrDirectoryTypesUnmodifiedGcode( self.filenameInput.value, import_translator.getGNUTranslatorFileTypes(), self.filenameInput.wasCancelled )
- for filename in filenames:
- writeOutput( filename )
+ def parseInitialization( self, combPreferences ):
+ "Parse gcode initialization and store the parameters."
+ for self.lineIndex in xrange( len( self.lines ) ):
+ line = self.lines[ self.lineIndex ]
+ splitLine = line.split()
+ firstWord = gcodec.getFirstWord( splitLine )
+ if firstWord == '(<bridgeExtrusionWidthOverSolid>':
+ self.bridgeExtrusionWidthOverSolid = float( splitLine[ 1 ] )
+ elif firstWord == '(<decimalPlacesCarried>':
+ self.decimalPlacesCarried = int( splitLine[ 1 ] )
+ elif firstWord == '(<extrusionStart>':
+ self.addLine( '(<procedureDone> comb )' )
+ return
+ elif firstWord == '(<extrusionWidth>':
+ self.extrusionWidth = float( splitLine[ 1 ] )
+ self.arrivalInsetFollowDistance = combPreferences.arrivalInsetFollowDistanceOverExtrusionWidth.value * self.extrusionWidth
+ self.closeSquared = 0.01 * self.extrusionWidth * self.extrusionWidth
+ self.jitter = combPreferences.jitterOverExtrusionWidth.value * self.extrusionWidth
+ elif firstWord == '(<fillInset>':
+ self.fillInset = float( splitLine[ 1 ] )
+ self.addLine( line )
+
+ def parseLine( self, combPreferences, line ):
+ "Parse a gcode line."
+ splitLine = line.split()
+ if len( splitLine ) < 1:
+ return
+ firstWord = splitLine[ 0 ]
+ if firstWord == 'G1':
+ if self.isPerimeter:
+ location = gcodec.getLocationFromSplitLine( None, splitLine )
+ if self.perimeter == None:
+ self.perimeter = []
+ self.perimeter.append( location )
+ self.pointTable[ str( location ) ] = self.perimeter
+ elif firstWord == 'M103':
+ self.boundaryLoop = None
+ if self.perimeter != None:
+ if len( self.perimeter ) > 2:
+ if self.perimeter[ 0 ] == self.perimeter[ - 1 ]:
+ del self.perimeter[ - 1 ]
+ self.perimeter = None
+ self.isPerimeter = False
+ elif firstWord == '(<boundaryPoint>':
+ location = gcodec.getLocationFromSplitLine( None, splitLine )
+ self.addToLoop( location )
+ elif firstWord == '(<layerStart>':
+ self.boundaryLoop = None
+ self.layer = None
+ self.perimeter = None
+ self.oldZ = float( splitLine[ 1 ] )
+ elif firstWord == '(<perimeter>':
+ self.isPerimeter = True
def main( hashtable = None ):
diff --git a/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/fill.py b/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/fill.py
index 7f93f0fb..3327eebf 100644
--- a/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/fill.py
+++ b/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/fill.py
@@ -58,26 +58,32 @@ __author__ = "Enrique Perez (perez_enrique@yahoo.com)"
__date__ = "$Date: 2008/28/04 $"
__license__ = "GPL 3.0"
-#looptailor
-#add raft outline temperature http://hydraraptor.blogspot.com/2008/09/screw-top-pot.html
#check loops for intersections with their own arounds
+#comb around, back
#array_place
-#comb back
-#change material
#one direction for while, one direction narrow then wide, split to weave, hex fill, loop inside sparse fill or run along sparse infill, fill in one direction for a number of layers
+#distance option
+#change material
#raft supports overhangs
+#document gear script
+#email marcus about peek extruder, raft problem and gear script http://reprap.org/bin/view/Main/ExtruderImprovementsAndAlternatives
#mosaic
#transform
#pick and place
#stack
#infill first
#searchable help
+#faster
#custom inclined plane, inclined plane from model, screw, fillet travel as well maybe
#later maybe addAroundClosest around arounds and check for closeness to other infills
#maybe much afterwards make congajure multistep view
#maybe bridge supports although staggered spans are probably better
#maybe update slice to add perimeter path intersection information to the large loop also
#maybe stripe although mosaic alone can handle it
+#stretch fiber around shape
+#multiple heads around edge
+#angle shape for overhang extrusions
+#free fabricator
def addAroundClosest( arounds, layerExtrusionWidth, paths, removedEndpoint ):
"Add the closest removed endpoint to the path, with minimal twisting."
removedEndpointPoint = removedEndpoint.point
@@ -176,7 +182,7 @@ def getExtraFillLoops( insideLoops, outsideLoop, radius ):
centers = intercircle.getCentersFromCircleNodes( circleNodes )
otherLoops = insideLoops + [ outsideLoop ]
for center in centers:
- inset = intercircle.getInsetFromClockwiseLoop( center, radius )
+ inset = intercircle.getSimplifiedInsetFromClockwiseLoop( center, radius )
if euclidean.isLargeSameDirection( inset, center, muchGreaterThanRadius ):
if isPathAlwaysInsideLoop( outsideLoop, inset ):
if isPathAlwaysOutsideLoops( insideLoops, inset ):
@@ -338,9 +344,6 @@ class FillSkein:
def addFill( self, layerIndex ):
"Add fill to the slice layer."
-# if layerIndex > 0:
-# return
-# print( 'layerIndex ' + str( layerIndex ) )
alreadyFilledArounds = []
arounds = []
back = - 999999999.0
@@ -393,11 +396,11 @@ class FillSkein:
circleNodes = intercircle.getCircleNodesFromLoop( planeRotatedPerimeter, slightlyGreaterThanFill )
centers = intercircle.getCentersFromCircleNodes( circleNodes )
for center in centers:
- alreadyFilledInset = intercircle.getInsetFromClockwiseLoop( center, layerFillInset )
+ alreadyFilledInset = intercircle.getSimplifiedInsetFromClockwiseLoop( center, layerFillInset )
if euclidean.getMaximumSpan( alreadyFilledInset ) > muchGreaterThanLayerFillInset or euclidean.isWiddershins( alreadyFilledInset ):
alreadyFilledLoop.append( alreadyFilledInset )
- around = intercircle.getInsetFromClockwiseLoop( center, aroundInset )
- if euclidean.isPathInsideLoop( planeRotatedPerimeter, around ) != euclidean.isWiddershins( planeRotatedPerimeter ):
+ around = intercircle.getSimplifiedInsetFromClockwiseLoop( center, aroundInset )
+ if euclidean.isPathInsideLoop( planeRotatedPerimeter, around ) == euclidean.isWiddershins( planeRotatedPerimeter ):
if euclidean.getMaximumSpan( alreadyFilledInset ) > muchGreaterThanLayerFillInset:
arounds.append( around )
for point in around:
diff --git a/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/hop.py b/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/hop.py
index ba4f1406..b982726e 100644
--- a/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/hop.py
+++ b/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/hop.py
@@ -1,8 +1,8 @@
"""
Hop is a script to raise the extruder when it is not extruding.
-The default 'Activate Hop' checkbox is on. When it is on, the functions described below will work, when it is off, the functions
-will not be called.
+The default 'Activate Hop' checkbox is off. It is off because Vik and Nophead found better results without hopping. When it
+is on, the functions described below will work, when it is off, the functions will not be called.
The important value for the hop preferences is "Hop Over Extrusion Height (ratio)" which is the ratio of the hop height over the
extrusion height, the default is 1.0. The 'Minimum Hop Angle (degrees)' is the minimum angle that the path of the extruder
@@ -249,7 +249,7 @@ class HopPreferences:
"Set the default preferences, execute title & preferences filename."
#Set the default preferences.
self.archive = []
- self.activateHop = preferences.BooleanPreference().getFromValue( 'Activate Hop', True )
+ self.activateHop = preferences.BooleanPreference().getFromValue( 'Activate Hop', False )
self.archive.append( self.activateHop )
self.filenameInput = preferences.Filename().getFromFilename( import_translator.getGNUTranslatorGcodeFileTypeTuples(), 'Open File to be Hopped', '' )
self.archive.append( self.filenameInput )
diff --git a/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/nozzle_wipe.py b/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/nozzle_wipe.py
index 20cf9bd2..98395865 100644
--- a/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/nozzle_wipe.py
+++ b/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/nozzle_wipe.py
@@ -92,10 +92,6 @@ __date__ = "$Date: 2008/21/04 $"
__license__ = "GPL 3.0"
-def getIntermediateLocation( alongWay, begin, end ):
- "Get the intermediate location between begin and end."
- return ( begin.times( 1.0 - alongWay ) ).plus( end.times( alongWay ) )
-
def getNozzleWipeChainGcode( filename, gcodeText, nozzleWipePreferences = None ):
"Nozzle wipe a gcode linear move text. Chain nozzle wipe the gcode if it is not already nozzle wiped."
gcodeText = gcodec.getGcodeFileText( filename, gcodeText )
@@ -160,10 +156,10 @@ class NozzleWipeSkein:
if beginEndDistance < 3.0 * self.extrusionWidth:
return
alongWay = self.extrusionWidth / beginEndDistance
- closeToOldLocation = getIntermediateLocation( alongWay, begin, end )
+ closeToOldLocation = euclidean.getIntermediateLocation( alongWay, begin, end )
closeToOldLocation.z = self.highestZ
self.addLine( self.getLinearMoveWithFeedrate( self.feedrateMinute, closeToOldLocation ) )
- closeToOldArrival = getIntermediateLocation( alongWay, end, begin )
+ closeToOldArrival = euclidean.getIntermediateLocation( alongWay, end, begin )
closeToOldArrival.z = self.highestZ
self.addLine( self.getLinearMoveWithFeedrate( self.feedrateMinute, closeToOldArrival ) )
@@ -190,13 +186,13 @@ class NozzleWipeSkein:
feedrateOverThree = 0.33333 * self.feedrateMinute
if arrivalWipeDistance > 2.0 * self.extrusionWidth:
alongWay = self.extrusionWidth / arrivalWipeDistance
- justBeforeWipeLocation = getIntermediateLocation( alongWay, self.locationWipe, self.locationArrival )
+ justBeforeWipeLocation = euclidean.getIntermediateLocation( alongWay, self.locationWipe, self.locationArrival )
self.addLine( self.getLinearMoveWithFeedrate( feedrateOverThree, justBeforeWipeLocation ) )
self.addLine( self.getLinearMoveWithFeedrate( self.feedrateMinute, self.locationWipe ) )
wipeDepartureDistance = self.locationWipe.distance( self.locationDeparture )
if wipeDepartureDistance > 2.0 * self.extrusionWidth:
alongWay = self.extrusionWidth / wipeDepartureDistance
- justAfterWipeLocation = getIntermediateLocation( alongWay, self.locationWipe, self.locationDeparture )
+ justAfterWipeLocation = euclidean.getIntermediateLocation( alongWay, self.locationWipe, self.locationDeparture )
self.addLine( self.getLinearMoveWithFeedrate( feedrateOverThree, justAfterWipeLocation ) )
self.addLine( self.getLinearMoveWithFeedrate( self.feedrateMinute, self.locationDeparture ) )
self.addHop( self.locationDeparture, location )
@@ -228,9 +224,7 @@ class NozzleWipeSkein:
for self.lineIndex in range( len( self.lines ) ):
line = self.lines[ self.lineIndex ]
splitLine = line.split()
- firstWord = ''
- if len( splitLine ) > 0:
- firstWord = splitLine[ 0 ]
+ firstWord = gcodec.getFirstWord( splitLine )
if firstWord == '(<decimalPlacesCarried>':
self.decimalPlacesCarried = int( splitLine[ 1 ] )
elif firstWord == '(<extrusionStart>':
diff --git a/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/raft.py b/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/raft.py
index f2921ec2..e3f92391 100644
--- a/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/raft.py
+++ b/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/raft.py
@@ -63,8 +63,9 @@ The following examples raft the files Hollow Square.gcode & Hollow Square.gts.
which contains Hollow Square.gcode, Hollow Square.gts and raft.py. The raft function will raft if
"Activate Raft, Elevate Nozzle, Orbit and Set Altitude" is true, which can be set in the dialog or by changing the preferences file
'raft.csv' with a text editor or a spreadsheet program set to separate tabs. The functions writeOutput and getRaftChainGcode
-check to see if the text has been rafted, if not they call getCombChainGcode in comb.py to get combed gcode; once they have
-the combed text, then they raft.
+check to see if the text has been rafted, if not they call getClipChainGcode in clip.py to get clipped gcode; once they have
+the clipped text, then they raft. Pictures of rafting in action are available from the Metalab blog at:
+http://reprap.soup.io/?search=rafting
> python raft.py
@@ -117,7 +118,7 @@ from skeinforge_tools.skeinforge_utilities import gcodec
from skeinforge_tools.skeinforge_utilities import intercircle
from skeinforge_tools.skeinforge_utilities import preferences
from skeinforge_tools import analyze
-from skeinforge_tools import comb
+from skeinforge_tools import clip
from skeinforge_tools import import_translator
from skeinforge_tools import material
from skeinforge_tools import polyfile
@@ -132,12 +133,12 @@ __date__ = "$Date: 2008/21/04 $"
__license__ = "GPL 3.0"
-#maybe cool for a minute
+#raft outline temperature http://hydraraptor.blogspot.com/2008/09/screw-top-pot.html
def getRaftChainGcode( filename, gcodeText, raftPreferences = None ):
"Raft a gcode linear move text. Chain raft the gcode if it is not already rafted."
gcodeText = gcodec.getGcodeFileText( filename, gcodeText )
- if not gcodec.isProcedureDone( gcodeText, 'comb' ):
- gcodeText = comb.getCombChainGcode( filename, gcodeText )
+ if not gcodec.isProcedureDone( gcodeText, 'clip' ):
+ gcodeText = clip.getClipChainGcode( filename, gcodeText )
return getRaftGcode( gcodeText, raftPreferences )
def getRaftGcode( gcodeText, raftPreferences = None ):
@@ -394,9 +395,7 @@ class RaftSkein:
for self.lineIndex in range( len( self.lines ) ):
line = self.lines[ self.lineIndex ]
splitLine = line.split()
- firstWord = ''
- if len( splitLine ) > 0:
- firstWord = splitLine[ 0 ]
+ firstWord = gcodec.getFirstWord( splitLine )
if firstWord == '(<decimalPlacesCarried>':
self.decimalPlacesCarried = int( splitLine[ 1 ] )
elif firstWord == '(<extrusionDiameter>':
@@ -452,10 +451,8 @@ class RaftSkein:
"Set maximum and minimum corners and z."
layerIndex = - 1
for line in self.lines[ self.lineIndex : ]:
- splitLine = line.split( ' ' )
- firstWord = ''
- if len( splitLine ) > 0:
- firstWord = splitLine[ 0 ]
+ splitLine = line.split()
+ firstWord = gcodec.getFirstWord( splitLine )
if firstWord == 'G1':
location = gcodec.getLocationFromSplitLine( self.oldLocation, splitLine )
self.cornerHigh = euclidean.getPointMaximum( self.cornerHigh, location )
diff --git a/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/skeinforge_utilities/euclidean.py b/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/skeinforge_utilities/euclidean.py
index 7dc17d49..2d1a75fe 100644
--- a/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/skeinforge_utilities/euclidean.py
+++ b/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/skeinforge_utilities/euclidean.py
@@ -51,11 +51,7 @@ def addSurroundingLoopBeginning( loop, skein ):
def addToThreadsFromLoop( extrusionHalfWidthSquared, gcodeType, loop, oldOrderedLocation, skein ):
"Add to threads from the last location from loop."
- nearestIndex = int( round( getNearestDistanceSquaredIndex( oldOrderedLocation, loop ).imag ) )
- loop = getAroundLoop( nearestIndex, nearestIndex, loop )
- nearestPoint = getNearestPointOnSegment( loop[ 0 ], loop[ 1 ], oldOrderedLocation )
- if nearestPoint.distance2( loop[ 0 ] ) > extrusionHalfWidthSquared and nearestPoint.distance2( loop[ 1 ] ) > extrusionHalfWidthSquared:
- loop = [ nearestPoint ] + loop[ 1 : ] + [ loop[ 0 ] ]
+ loop = getLoopStartingNearest( extrusionHalfWidthSquared, oldOrderedLocation, loop )
oldOrderedLocation.setToVec3( loop[ 0 ] )
skein.addLine( gcodeType )
skein.addGcodeFromThread( loop + [ loop[ 0 ] ] ) # Turn extruder on and indicate that a loop is beginning.
@@ -117,6 +113,32 @@ def getAwayPath( path, radius ):
away.append( point )
return away
+def getClippedLoopPath( clip, loopPath ):
+ "Get a clipped loop path."
+ if clip <= 0.0:
+ return loopPath
+ loopPathLength = getPathLength( loopPath )
+ lastLength = 0.0
+ pointIndex = 0
+ totalLength = 0.0
+ clippedLength = loopPathLength - clip
+ while totalLength < clippedLength and pointIndex < len( loopPath ) - 1:
+ firstPoint = loopPath[ pointIndex ]
+ secondPoint = loopPath[ pointIndex + 1 ]
+ pointIndex += 1
+ lastLength = totalLength
+ totalLength += firstPoint.distance( secondPoint )
+ remainingLength = clippedLength - lastLength
+ clippedLoopPath = loopPath[ : pointIndex ]
+ ultimateClippedPoint = loopPath[ pointIndex ]
+ penultimateClippedPoint = clippedLoopPath[ - 1 ]
+ segment = ultimateClippedPoint.minus( penultimateClippedPoint )
+ segmentLength = segment.length()
+ if segmentLength <= 0.0:
+ return clippedLoopPath
+ newUltimatePoint = penultimateClippedPoint.plus( segment.times( remainingLength / segmentLength ) )
+ return clippedLoopPath + [ newUltimatePoint ]
+
def getComplexCrossProduct( firstComplex, secondComplex ):
"Get z component cross product of a pair of complexes."
return firstComplex.real * secondComplex.imag - firstComplex.imag * secondComplex.real
@@ -212,6 +234,10 @@ def getInsidesAddToOutsides( loops, outsides ):
outsides.append( loop )
return insides
+def getIntermediateLocation( alongWay, begin, end ):
+ "Get the intermediate location between begin and end."
+ return ( begin.times( 1.0 - alongWay ) ).plus( end.times( alongWay ) )
+
def getLeftPoint( path ):
"Get the leftmost point in the path."
left = 999999999.0
@@ -222,6 +248,17 @@ def getLeftPoint( path ):
leftPoint = point
return leftPoint
+def getLoopStartingNearest( extrusionHalfWidthSquared, location, loop ):
+ "Add to threads from the last location from loop."
+ nearestIndex = int( round( getNearestDistanceSquaredIndex( location, loop ).imag ) )
+ loop = getAroundLoop( nearestIndex, nearestIndex, loop )
+ nearestPoint = getNearestPointOnSegment( loop[ 0 ], loop[ 1 ], location )
+ if nearestPoint.distance2( loop[ 0 ] ) > extrusionHalfWidthSquared and nearestPoint.distance2( loop[ 1 ] ) > extrusionHalfWidthSquared:
+ loop = [ nearestPoint ] + loop[ 1 : ] + [ loop[ 0 ] ]
+ elif nearestPoint.distance2( loop[ 0 ] ) > nearestPoint.distance2( loop[ 1 ] ):
+ loop = loop[ 1 : ] + [ loop[ 0 ] ]
+ return loop
+
def getMaximumSpan( loop ):
"Get the maximum span in the xy plane."
extent = getComplexMaximumFromVec3List( loop ) - getComplexMinimumFromVec3List( loop )
@@ -565,6 +602,19 @@ def isLineIntersectingInsideXSegment( segmentFirstX, segmentSecondX, vector3Firs
return False
return xIntersection < max( segmentFirstX, segmentSecondX )
+def isLineIntersectingLoops( loops, pointBegin, pointEnd ):
+ "Determine if the line is intersecting loops."
+ normalizedSegment = pointEnd.dropAxis( 2 ) - pointBegin.dropAxis( 2 )
+ normalizedSegmentLength = abs( normalizedSegment )
+ if normalizedSegmentLength > 0.0:
+ normalizedSegment /= normalizedSegmentLength
+ segmentYMirror = complex( normalizedSegment.real, - normalizedSegment.imag )
+ pointBeginRotated = getRoundZAxisByPlaneAngle( segmentYMirror, pointBegin )
+ pointEndRotated = getRoundZAxisByPlaneAngle( segmentYMirror, pointEnd )
+ if isLoopListIntersectingInsideXSegment( loops, pointBeginRotated.x, pointEndRotated.x, segmentYMirror, pointBeginRotated.y ):
+ return True
+ return False
+
def isLoopIntersectingInsideXSegment( loop, segmentFirstX, segmentSecondX, segmentYMirror, y ):
"Determine if the loop is intersecting inside the x segment."
rotatedLoop = getPathRoundZAxisByPlaneAngle( segmentYMirror, loop )
@@ -580,15 +630,8 @@ def isLoopIntersectingLoops( loop, otherLoops ):
for pointIndex in range( len( loop ) ):
pointBegin = loop[ pointIndex ]
pointEnd = loop[ ( pointIndex + 1 ) % len( loop ) ]
- normalizedSegment = pointEnd.dropAxis( 2 ) - pointBegin.dropAxis( 2 )
- normalizedSegmentLength = abs( normalizedSegment )
- if normalizedSegmentLength > 0.0:
- normalizedSegment /= normalizedSegmentLength
- segmentYMirror = complex( normalizedSegment.real, - normalizedSegment.imag )
- pointBeginRotated = getRoundZAxisByPlaneAngle( segmentYMirror, pointBegin )
- pointEndRotated = getRoundZAxisByPlaneAngle( segmentYMirror, pointEnd )
- if isLoopListIntersectingInsideXSegment( otherLoops, pointBeginRotated.x, pointEndRotated.x, segmentYMirror, pointBeginRotated.y ):
- return True
+ if isLineIntersectingLoops( otherLoops, pointBegin, pointEnd ):
+ return True
return False
def isLoopListIntersectingInsideXSegment( loopList, segmentFirstX, segmentSecondX, segmentYMirror, y ):
diff --git a/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/skeinforge_utilities/gcodec.py b/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/skeinforge_utilities/gcodec.py
index 23346861..1e2cad39 100644
--- a/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/skeinforge_utilities/gcodec.py
+++ b/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/skeinforge_utilities/gcodec.py
@@ -228,7 +228,7 @@ def getTextLines( text ):
def getUnmodifiedGCodeFiles( fileInDirectory = '' ):
"Get gcode files which are not modified."
- words = '_comb,_comment,_cool,_fill,_fillet,_hop,_oozebane,_raft,_slice,_statistic,_stretch,_tower,_transform,_wipe'.split( ',' )
+ words = '_clip _comb _comment _cool _fill _fillet _hop _nozzle_wipe _oozebane _raft _slice _statistic _stretch _tower _transform _wipe'.split()
return getFilesWithFileTypeWithoutWords( 'gcode', words, fileInDirectory )
def indexOfStartingWithSecond( letter, splitLine ):
@@ -279,9 +279,12 @@ def replaceWords( filenames, original, replacement ):
for filename in filenames:
fileText = getFileText( filename )
if fileText != '':
- print( filename )
- fileText = fileText.replace( original, replacement )
- writeFileText( filename, fileText )
+ whereInText = fileText.find( original )
+ if whereInText != - 1:
+ print( filename )
+ print( whereInText )
+ fileText = fileText.replace( original, replacement )
+ writeFileText( filename, fileText )
def writeFileMessageEnd( end, filename, fileText, message ):
"Write to a filename with a suffix and print a message."
diff --git a/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/skeinforge_utilities/intercircle.py b/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/skeinforge_utilities/intercircle.py
index 21b8a9bc..6cfec8ab 100644
--- a/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/skeinforge_utilities/intercircle.py
+++ b/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/skeinforge_utilities/intercircle.py
@@ -60,7 +60,7 @@ def addOperatingOrbits( operatingJump, skein, temperatureChangeTime ):
for boundaryLoop in skein.boundaryLoops:
centers = getCentersFromLoopDirection( True, boundaryLoop, greaterThanPerimeterOutset )
for center in centers:
- outset = getInsetFromClockwiseLoop( center, perimeterOutset )
+ outset = getSimplifiedInsetFromClockwiseLoop( center, perimeterOutset )
if euclidean.isLargeSameDirection( outset, center, perimeterOutset ):
loopLength = euclidean.getPolygonLength( outset )
if loopLength > largestLength:
@@ -138,7 +138,7 @@ def getCentersFromOutside( isOutside, loop, radius ):
outsideCenters = []
halfRadius = 0.5 * radius
for center in centers:
- inset = getInsetFromClockwiseLoop( center, halfRadius )
+ inset = getSimplifiedInsetFromClockwiseLoop( center, halfRadius )
if euclidean.isPathInsideLoop( loop, inset ) != isOutside:
outsideCenters.append( center )
return outsideCenters
@@ -192,16 +192,6 @@ def getCircleNodesFromPath( path, radius ):
circleNodes.append( CircleNode().getFromCircleRadius( point, len( circleNodes ), radius ) )
return circleNodes
-def getInsetFromClockwiseLoop( loop, radius ):
- "Get loop inset from clockwise loop, out from widdershins loop."
- insetLoop = []
- for pointIndex in range( len( loop ) ):
- behindAbsolute = loop[ ( pointIndex + len( loop ) - 1 ) % len( loop ) ]
- center = loop[ pointIndex ]
- aheadAbsolute = loop[ ( pointIndex + 1 ) % len( loop ) ]
- insetLoop.append( getInsetFromClockwiseTriple( aheadAbsolute, behindAbsolute, center, radius ) )
- return getWithoutIntersections( euclidean.getSimplifiedLoop( insetLoop, radius ) )
-
def getInsetFromClockwiseTriple( aheadAbsolute, behindAbsolute, center, radius ):
"Get loop inset from clockwise triple, out from widdershins loop."
originalCenterMinusBehind = center.minus( behindAbsolute )
@@ -223,6 +213,16 @@ def getInsetFromClockwiseTriple( aheadAbsolute, behindAbsolute, center, radius )
between = Vec3( x, behindIntersection.y, behindIntersection.z )
return euclidean.getRoundZAxisByPlaneAngle( centerRoundZAngle, between )
+def getInsetFromClockwiseLoop( loop, radius ):
+ "Get loop inset from clockwise loop, out from widdershins loop."
+ insetLoop = []
+ for pointIndex in range( len( loop ) ):
+ behindAbsolute = loop[ ( pointIndex + len( loop ) - 1 ) % len( loop ) ]
+ center = loop[ pointIndex ]
+ aheadAbsolute = loop[ ( pointIndex + 1 ) % len( loop ) ]
+ insetLoop.append( getInsetFromClockwiseTriple( aheadAbsolute, behindAbsolute, center, radius ) )
+ return insetLoop
+
def getIntersectionAtInset( ahead, behind, inset ):
"Get circle intersection loop at inset from segment."
aheadMinusBehind = ahead.minus( behind )
@@ -241,6 +241,10 @@ def getLoopsFromLoopsDirection( isWiddershins, loops ):
directionalLoops.append( loop )
return directionalLoops
+def getSimplifiedInsetFromClockwiseLoop( loop, radius ):
+ "Get loop inset from clockwise loop, out from widdershins loop."
+ return getWithoutIntersections( euclidean.getSimplifiedLoop( getInsetFromClockwiseLoop( loop, radius ), radius ) )
+
def getWithoutIntersections( loop ):
"Get loop without intersections."
lastLoopLength = len( loop )
@@ -326,7 +330,7 @@ class BoundingLoop:
outsetBoundingLoop.minimum = self.minimum - complex( outsetDistance, outsetDistance )
greaterThanOutsetDistance = 1.1 * outsetDistance
centers = getCentersFromLoopDirection( True, self.loop, greaterThanOutsetDistance )
- outsetBoundingLoop.loop = getInsetFromClockwiseLoop( centers[ 0 ], outsetDistance )
+ outsetBoundingLoop.loop = getSimplifiedInsetFromClockwiseLoop( centers[ 0 ], outsetDistance )
return outsetBoundingLoop
def isEntirelyInsideAnother( self, anotherBoundingLoop ):
diff --git a/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/slice_shape.py b/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/slice_shape.py
index 31a7897b..4398c75d 100644
--- a/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/slice_shape.py
+++ b/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/slice_shape.py
@@ -101,7 +101,7 @@ def addAlreadyFilledArounds( alreadyFilledArounds, loop, radius ):
circleNodes = intercircle.getCircleNodesFromLoop( loop, slightlyGreaterThanRadius )
centers = intercircle.getCentersFromCircleNodes( circleNodes )
for center in centers:
- alreadyFilledInset = intercircle.getInsetFromClockwiseLoop( center, radius )
+ alreadyFilledInset = intercircle.getSimplifiedInsetFromClockwiseLoop( center, radius )
if euclidean.getMaximumSpan( alreadyFilledInset ) > muchGreaterThanRadius or euclidean.isWiddershins( alreadyFilledInset ):
alreadyFilledLoop.append( alreadyFilledInset )
@@ -120,6 +120,57 @@ def addPointsAtZ( edgePair, points, radius, vertices, z ):
sliceIntersectionSecond = getSliceIntersectionFromEdge( edgePair.edges[ 1 ], vertices, z )
intercircle.addPointsFromSegment( points, radius, sliceIntersectionFirst, sliceIntersectionSecond )
+def addSegmentOutline( isThick, outlines, pointBegin, pointEnd, width ):
+ "Add a diamond or hexagonal outline for a line segment."
+ exclusionWidth = 0.6 * width
+ slope = 0.3
+ if isThick:
+ slope = 3.0
+ exclusionWidth = 0.8 * width
+ segment = pointEnd.dropAxis( 2 ) - pointBegin.dropAxis( 2 )
+ segmentLength = abs( segment )
+ if segmentLength == 0.0:
+ return
+ normalizedSegment = segment / segmentLength
+ outline = []
+ segmentYMirror = complex( normalizedSegment.real, - normalizedSegment.imag )
+ pointBeginRotated = euclidean.getRoundZAxisByPlaneAngle( segmentYMirror, pointBegin )
+ pointEndRotated = euclidean.getRoundZAxisByPlaneAngle( segmentYMirror, pointEnd )
+ along = 0.01
+ alongLength = along * segmentLength
+ if alongLength > 0.1 * exclusionWidth:
+ along *= 0.1 * exclusionWidth / alongLength
+ alongEnd = 1.0 - along
+ remainingToHalf = 0.5 - along
+ alongToWidth = exclusionWidth / slope / segmentLength
+ pointBeginIntermediate = euclidean.getIntermediateLocation( along, pointBeginRotated, pointEndRotated )
+ pointEndIntermediate = euclidean.getIntermediateLocation( alongEnd, pointBeginRotated, pointEndRotated )
+ outline.append( pointBeginIntermediate )
+ verticalWidth = Vec3( 0.0, exclusionWidth, 0.0 )
+ if alongToWidth > 0.9 * remainingToHalf:
+ verticalWidth = Vec3( 0.0, slope * remainingToHalf, 0.0 )
+ middle = ( pointBeginIntermediate.plus( pointEndIntermediate ) ).times( 0.5 )
+ middleDown = middle.minus( verticalWidth )
+ middleUp = middle.plus( verticalWidth )
+ outline.append( middleUp )
+ outline.append( pointEndIntermediate )
+ outline.append( middleDown )
+ else:
+ alongOutsideBegin = along + alongToWidth
+ alongOutsideEnd = alongEnd - alongToWidth
+ outsideBeginCenter = euclidean.getIntermediateLocation( alongOutsideBegin, pointBeginRotated, pointEndRotated )
+ outsideBeginCenterDown = outsideBeginCenter.minus( verticalWidth )
+ outsideBeginCenterUp = outsideBeginCenter.plus( verticalWidth )
+ outsideEndCenter = euclidean.getIntermediateLocation( alongOutsideEnd, pointBeginRotated, pointEndRotated )
+ outsideEndCenterDown = outsideEndCenter.minus( verticalWidth )
+ outsideEndCenterUp = outsideEndCenter.plus( verticalWidth )
+ outline.append( outsideBeginCenterUp )
+ outline.append( outsideEndCenterUp )
+ outline.append( pointEndIntermediate )
+ outline.append( outsideEndCenterDown )
+ outline.append( outsideBeginCenterDown )
+ outlines.append( euclidean.getPathRoundZAxisByPlaneAngle( normalizedSegment, outline ) )
+
def getCommonVertexIndex( edgeFirst, edgeSecond ):
"Get the vertex index that both edges have in common."
for edgeFirstVertexIndex in edgeFirst.vertexIndexes:
@@ -285,7 +336,7 @@ def getRemainingEdgeTable( edges, vertices, z ):
return remainingEdgeTable
def getSegmentsFromPoints( loopLists, pointBegin, pointEnd ):
- "Get enpoint segments from the beginning and end of a line segment."
+ "Get endpoint segments from the beginning and end of a line segment."
normalizedSegment = pointEnd.dropAxis( 2 ) - pointBegin.dropAxis( 2 )
normalizedSegmentLength = abs( normalizedSegment )
if normalizedSegmentLength == 0.0:
@@ -372,6 +423,17 @@ def isIntersectingWithinLists( loop, loopLists ):
return True
return False
+def isIntersectingItself( loop, width ):
+ "Determine if the loop is intersecting itself."
+ outlines = []
+ for pointIndex in xrange( len( loop ) ):
+ pointBegin = loop[ pointIndex ]
+ pointEnd = loop[ ( pointIndex + 1 ) % len( loop ) ]
+ if euclidean.isLineIntersectingLoops( outlines, pointBegin, pointEnd ):
+ return True
+ addSegmentOutline( False, outlines, pointBegin, pointEnd, width )
+ return False
+
def isZInEdge( edge, vertices, z ):
"Determine if z is inside the edge."
vertex1ZHigher = vertices[ edge.vertexIndexes[ 0 ] ].z > z
@@ -434,13 +496,24 @@ class SliceSkein:
if lowerFilename in directory:
self.addFromFile( os.path.join( gcodeDirectoryPath, filename.lower() ) )
- def addGcodeFromPerimeterPaths( self, loop, loopLists, radius ):
+ def addGcodeFromPerimeterPaths( self, isIntersectingSelf, loop, loopLists, radius ):
"Add the perimeter paths to the output."
segments = []
+ outlines = []
+ thickOutlines = []
+ allLoopLists = loopLists[ : ] + [ thickOutlines ]
for pointIndex in range( len( loop ) ):
pointBegin = loop[ pointIndex ]
pointEnd = loop[ ( pointIndex + 1 ) % len( loop ) ]
- segments += getSegmentsFromPoints( loopLists, pointBegin, pointEnd )
+ if isIntersectingSelf:
+ if euclidean.isLineIntersectingLoops( outlines, pointBegin, pointEnd ):
+ segments += getSegmentsFromPoints( allLoopLists, pointBegin, pointEnd )
+ else:
+ segments += getSegmentsFromPoints( loopLists, pointBegin, pointEnd )
+ addSegmentOutline( False, outlines, pointBegin, pointEnd, self.extrusionWidth )
+ addSegmentOutline( True, thickOutlines, pointBegin, pointEnd, self.extrusionWidth )
+ else:
+ segments += getSegmentsFromPoints( loopLists, pointBegin, pointEnd )
perimeterPaths = []
path = []
muchSmallerThanRadius = 0.1 * radius
@@ -463,8 +536,9 @@ class SliceSkein:
def addGcodeFromRemainingLoop( self, loop, loopLists, radius ):
"Add the remainder of the loop which does not overlap the alreadyFilledArounds loops."
euclidean.addSurroundingLoopBeginning( loop, self )
- if isIntersectingWithinLists( loop, loopLists ):
- self.addGcodeFromPerimeterPaths( loop, loopLists, radius )
+ isIntersectingSelf = isIntersectingItself( loop, self.extrusionWidth )
+ if isIntersectingWithinLists( loop, loopLists ) or isIntersectingSelf:
+ self.addGcodeFromPerimeterPaths( isIntersectingSelf, loop, loopLists, radius )
else:
self.addLine( '(<perimeter> )' ) # Indicate that a perimeter is beginning.
self.addGcodeFromThread( loop + [ loop[ 0 ] ] )
@@ -512,7 +586,7 @@ class SliceSkein:
self.addLine( '(<fillInset> ' + str( self.fillInset ) + ' )' ) # Set fill inset.
# Set bridge extrusion width over solid extrusion width.
self.addLine( '(<bridgeExtrusionWidthOverSolid> ' + euclidean.getRoundedToThreePlaces( self.bridgeExtrusionWidth / self.extrusionWidth ) + ' )' )
- self.addLine( '(<procedureDone> slice )' ) # The skein has been sliced.
+ self.addLine( '(<procedureDone> slice_shape )' ) # The skein has been sliced.
self.addLine( '(<extrusionStart> )' ) # Initialization is finished, extrusion is starting.
circleArea = self.extrusionDiameter * self.extrusionDiameter * math.pi / 4.0
print( 'The extrusion fill density ratio is ' + euclidean.getRoundedToThreePlaces( self.extrusionWidth * self.extrusionHeight / circleArea ) )
@@ -550,7 +624,7 @@ class SliceSkein:
for loop in self.belowLoops:
centers = intercircle.getCentersFromLoopDirection( True, loop, greaterThanOverhang )
for center in centers:
- outset = intercircle.getInsetFromClockwiseLoop( center, overhangInset )
+ outset = intercircle.getSimplifiedInsetFromClockwiseLoop( center, overhangInset )
if euclidean.isLargeSameDirection( outset, center, self.extrusionWidth ):
belowOutsetLoops.append( outset )
bridgeDirection = complex()
@@ -572,9 +646,10 @@ class SliceSkein:
circleNodes = intercircle.getCircleNodesFromLoop( loop, slightlyGreaterThanHalfWIdth )
centers = intercircle.getCentersFromCircleNodes( circleNodes )
for center in centers:
- extrudateLoop = intercircle.getInsetFromClockwiseLoop( center, halfWidth )
+ extrudateLoop = intercircle.getSimplifiedInsetFromClockwiseLoop( center, halfWidth )
if euclidean.isLargeSameDirection( extrudateLoop, center, muchGreaterThanHalfWIdth ):
if euclidean.isPathInsideLoop( loop, extrudateLoop ) == euclidean.isWiddershins( loop ):
+ extrudateLoop.reverse()
extrudateLoops.append( extrudateLoop )
return extrudateLoops
@@ -678,49 +753,43 @@ class SliceSkein:
self.addShutdownToOutput()
-#extrusionWidthOverDiameter
-#extrusionHeightOverDiameter
-#(<extrusionDiameter> 0.5 )
-#(<extrusionWidth> 0.599 )
-#(<fillInset> 0.449484698309 )
-#(<extrusionHeight> 0.4 )
class SlicePreferences:
"A class to handle the slice preferences."
def __init__( self ):
"Set the default preferences, execute title & preferences filename."
#Set the default preferences.
+ self.archive = []
self.extrusionDiameter = preferences.FloatPreference().getFromValue( 'Extrusion Diameter (mm):', 0.6 )
+ self.archive.append( self.extrusionDiameter )
self.extrusionDiameterOverPrecision = preferences.FloatPreference().getFromValue( 'Extrusion Diameter Over Precision (ratio):', 10.0 )
+ self.archive.append( self.extrusionDiameterOverPrecision )
self.extrusionHeightOverDiameter = preferences.FloatPreference().getFromValue( 'Extrusion Height Over Diameter (ratio):', 0.67 )
+ self.archive.append( self.extrusionHeightOverDiameter )
self.extrusionPerimeterWidthOverDiameter = preferences.FloatPreference().getFromValue( 'Extrusion Perimeter Width Over Diameter (ratio):', 1.2 )
+ self.archive.append( self.extrusionPerimeterWidthOverDiameter )
self.extrusionWidthOverDiameter = preferences.FloatPreference().getFromValue( 'Extrusion Width Over Diameter (ratio):', 1.0 )
+ self.archive.append( self.extrusionWidthOverDiameter )
self.filenameInput = preferences.Filename().getFromFilename( import_translator.getGNUTranslatorFileTypeTuples(), 'Open File to be Sliced', '' )
+ self.archive.append( self.filenameInput )
self.importCoarseness = preferences.FloatPreference().getFromValue( 'Import Coarseness (ratio):', 1.0 )
+ self.archive.append( self.importCoarseness )
importRadio = []
self.correct = preferences.RadioLabel().getFromRadioLabel( 'Correct Mesh', 'Mesh Type:', importRadio, True )
+ self.archive.append( self.correct )
self.unproven = preferences.Radio().getFromRadio( 'Unproven Mesh', importRadio,False )
+ self.archive.append( self.unproven )
self.infillBridgeWidthOverDiameter = preferences.FloatPreference().getFromValue( 'Infill Bridge Width Over Thickness (ratio):', 1.0 )
+ self.archive.append( self.infillBridgeWidthOverDiameter )
self.infillDirectionBridge = preferences.BooleanPreference().getFromValue( 'Infill in Direction of Bridges', True )
+ self.archive.append( self.infillDirectionBridge )
self.infillPerimeterOverlap = preferences.FloatPreference().getFromValue( 'Infill Perimeter Overlap (ratio):', 0.1 )
+ self.archive.append( self.infillPerimeterOverlap )
infillRadio = []
self.perimeterInfillPreference = preferences.RadioLabel().getFromRadioLabel( 'Calculate Overlap from Perimeter and Infill', 'Infill Perimeter Overlap Method of Calculation:', infillRadio, True )
+ self.archive.append( self.perimeterInfillPreference )
self.perimeterPreference = preferences.Radio().getFromRadio( 'Calculate Overlap from Perimeter Only', infillRadio, False )
+ self.archive.append( self.perimeterPreference )
#Create the archive, title of the execute button, title of the dialog & preferences filename.
- self.archive = [
- self.extrusionDiameter,
- self.extrusionDiameterOverPrecision,
- self.extrusionPerimeterWidthOverDiameter,
- self.extrusionHeightOverDiameter,
- self.extrusionWidthOverDiameter,
- self.filenameInput,
- self.importCoarseness,
- self.correct,
- self.unproven,
- self.infillBridgeWidthOverDiameter,
- self.infillDirectionBridge,
- self.infillPerimeterOverlap,
- self.perimeterInfillPreference,
- self.perimeterPreference ]
self.executeTitle = 'Slice'
self.filenamePreferences = preferences.getPreferencesFilePath( 'slice_shape.csv' )
self.filenameHelp = 'skeinforge_tools.slice_shape.html'
diff --git a/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/stretch.py b/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/stretch.py
index 20211460..336cdf4c 100644
--- a/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/stretch.py
+++ b/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/stretch.py
@@ -152,9 +152,7 @@ class LineIteratorBackward:
for lineIndex in xrange( self.lineIndex + 1, len( self.lines ) ):
line = self.lines[ lineIndex ]
splitLine = line.split()
- firstWord = ''
- if len( splitLine ) > 0:
- firstWord = splitLine[ 0 ]
+ firstWord = gcodec.getFirstWord( splitLine )
if firstWord == 'M103':
return lineIndex - 2
print( 'This should never happen in stretch, no deactivate command was found for this thread.' )
@@ -170,9 +168,7 @@ class LineIteratorBackward:
nextLineIndex = self.lineIndex - 1
line = self.lines[ self.lineIndex ]
splitLine = line.split()
- firstWord = ''
- if len( splitLine ) > 0:
- firstWord = splitLine[ 0 ]
+ firstWord = gcodec.getFirstWord( splitLine )
if firstWord == 'M103':
if self.isLoop:
nextLineIndex = self.getIndexBeforeNextDeactivate()
@@ -196,9 +192,7 @@ class LineIteratorBackward:
for lineIndex in xrange( self.lineIndex + 1, len( self.lines ) ):
line = self.lines[ lineIndex ]
splitLine = line.split()
- firstWord = ''
- if len( splitLine ) > 0:
- firstWord = splitLine[ 0 ]
+ firstWord = gcodec.getFirstWord( splitLine )
if firstWord == 'G1':
linearMoves += 1
if firstWord == 'M101':
@@ -222,9 +216,7 @@ class LineIteratorForward:
for lineIndex in xrange( self.lineIndex - 1, 3, - 1 ):
line = self.lines[ lineIndex ]
splitLine = line.split()
- firstWord = ''
- if len( splitLine ) > 0:
- firstWord = splitLine[ 0 ]
+ firstWord = gcodec.getFirstWord( splitLine )
if firstWord == 'M101':
return lineIndex + 1
print( 'This should never happen in stretch, no activate command was found for this thread.' )
@@ -240,9 +232,7 @@ class LineIteratorForward:
nextLineIndex = self.lineIndex + 1
line = self.lines[ self.lineIndex ]
splitLine = line.split()
- firstWord = ''
- if len( splitLine ) > 0:
- firstWord = splitLine[ 0 ]
+ firstWord = gcodec.getFirstWord( splitLine )
if firstWord == 'M103':
if self.isLoop:
nextLineIndex = self.getIndexJustAfterActivate()
@@ -263,7 +253,6 @@ class StretchSkein:
self.extrusionWidth = 0.4
self.feedrateMinute = 960.0
self.isLoop = False
- self.isPerimeter = False
self.lineIndex = 0
self.lines = None
self.oldLocation = None
@@ -362,9 +351,7 @@ class StretchSkein:
for lineIndex in xrange( self.lineIndex + 1, len( self.lines ) ):
line = self.lines[ lineIndex ]
splitLine = line.split()
- firstWord = ''
- if len( splitLine ) > 0:
- firstWord = splitLine[ 0 ]
+ firstWord = gcodec.getFirstWord( splitLine )
if firstWord == 'G1' or firstWord == 'M103':
return False
if firstWord == 'M101':
@@ -386,9 +373,7 @@ class StretchSkein:
for self.lineIndex in range( len( self.lines ) ):
line = self.lines[ self.lineIndex ]
splitLine = line.split()
- firstWord = ''
- if len( splitLine ) > 0:
- firstWord = splitLine[ 0 ]
+ firstWord = gcodec.getFirstWord( splitLine )
if firstWord == '(<bridgeExtrusionWidthOverSolid>':
self.bridgeExtrusionWidthOverSolid = float( splitLine[ 1 ] )
elif firstWord == '(<decimalPlacesCarried>':
@@ -416,7 +401,6 @@ class StretchSkein:
elif firstWord == 'M103':
self.extruderActive = False
self.isLoop = False
- self.isPerimeter = False
self.threadMaximumAbsoluteStretch = self.layerMaximumAbsoluteStretch
elif firstWord == '(<bridgeLayer>':
self.layerMaximumAbsoluteStretch = self.maximumAbsoluteStretch * self.bridgeExtrusionWidthOverSolid
@@ -430,7 +414,6 @@ class StretchSkein:
self.isLoop = True
elif firstWord == '(<perimeter>':
self.isLoop = True
- self.isPerimeter = True
self.threadMaximumAbsoluteStretch = self.perimeterMaximumAbsoluteStretch
self.addLine( line )
diff --git a/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/tower.py b/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/tower.py
index 9f1f4d32..fe4e0482 100644
--- a/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/tower.py
+++ b/trunk/reprap/miscellaneous/python-beanshell-scripts/skeinforge_tools/tower.py
@@ -26,7 +26,9 @@ The following examples tower the files Hollow Square.gcode & Hollow Square.gts.
which contains Hollow Square.gcode, Hollow Square.gts and tower.py. The tower function will tower if 'Maximum Tower Layers' is
greater than zero, which can be set in the dialog or by changing the preferences file 'tower.csv' with a text editor or a spreadsheet
program set to separate tabs. The functions writeOutput and getTowerChainGcode check to see if the text has been towered,
-if not they call the getFillChainGcode in fill.py to fill the text; once they have the filled text, then they tower.
+if not they call the getFillChainGcode in fill.py to fill the text; once they have the filled text, then they tower. Pictures of towering in
+action are available from the Metalab blog at:
+http://reprap.soup.io/?search=towering
> python tower.py