diff options
author | doomsay <doomsay@cb376a5e-1013-0410-a455-b6b1f9ac8223> | 2008-10-03 19:58:20 +0000 |
---|---|---|
committer | doomsay <doomsay@cb376a5e-1013-0410-a455-b6b1f9ac8223> | 2008-10-03 19:58:20 +0000 |
commit | 204cd4fff962e9e449e6cee3b95ca159b6610bb6 (patch) | |
tree | 394c381e88e072ff514e56731040400dc2f3329b | |
parent | 937e2d9b3d2dd6f0d43de1f7e63bf08416547ba9 (diff) | |
download | reprap-backup-204cd4fff962e9e449e6cee3b95ca159b6610bb6.tar.gz reprap-backup-204cd4fff962e9e449e6cee3b95ca159b6610bb6.zip |
git-svn-id: https://reprap.svn.sourceforge.net/svnroot/reprap@2058 cb376a5e-1013-0410-a455-b6b1f9ac8223
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 <br> <br> <br> +Motto<br> + <br> +I may be slow, but I get there in the end.<br> + <br> + <br> + <br> Troubleshooting<br> <br> You can ask for skeinforge help by posting in the "How to Print Gcode from Host" thread 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 vector file is saved as Screw Holder.svg< <td width="100%">Methods defined here:<br> <dl><dt><a name="VectorwritePreferences-__init__"><strong>__init__</strong></a>(self)</dt><dd><tt>Set the default preferences, execute title & preferences filename.</tt></dd></dl> -<dl><dt><a name="VectorwritePreferences-execute"><strong>execute</strong></a>(self)</dt><dd><tt>Write button has been 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 vector file is saved as Screw Holder.svg< <dl><dt><a name="VectorwriteSkein-addVectorWindow"><strong>addVectorWindow</strong></a>(self)</dt><dd><tt>Add a new vector window to vector windows.</tt></dd></dl> +<dl><dt><a name="VectorwriteSkein-execute"><strong>execute</strong></a>(self)</dt><dd><tt>Write button has been clicked.</tt></dd></dl> + <dl><dt><a name="VectorwriteSkein-getFilenameWriteFiles"><strong>getFilenameWriteFiles</strong></a>(self, filename)</dt><dd><tt>Write one or multiple files for the filename.</tt></dd></dl> <dl><dt><a name="VectorwriteSkein-getHypertextLinkBasename"><strong>getHypertextLinkBasename</strong></a>(self, baseUnderscoredPrefix, vectorWindowIndex)</dt><dd><tt>Get hypertext link basename for a numbered vector 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 is a script to comb the extrusion hair of a gcode file.<br> <br> -Comb bends the extruder travel paths around holes in the slice, to avoid stringers. The default 'Activate Comb' checkbox is on.<br> -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<br> -skeinforge chain. To run comb, in a shell type:<br> +The default 'Activate Comb' checkbox is on. When it is on, the functions described below will work, when it is off, the functions<br> +will not be called.<br> + <br> +Comb bends the extruder travel paths around holes in the slice, to avoid stringers and it jitters the loop end position to a different<br> +place on each layer to prevent the a ridge from forming. The "Jitter Over Extrusion Width (ratio)" is the ratio of the amount the<br> +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<br> +roughly the same place on each layer. To run comb, in a shell type:<br> > python comb.py<br> <br> The following examples comb the files Hollow Square.gcode & Hollow Square.gts. The examples are run in a terminal in the folder<br> @@ -21,7 +25,8 @@ which contains Hollow Square.gcode, Hollow Square.gts&n 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<br> editor or a spreadsheet program set to separate tabs. The functions writeOutput and getCombChainGcode check to see if the<br> text has been combed, if not they call getTowerChainGcode in tower.py to tower the text; once they have the towered text, then<br> -they comb.<br> +they comb. Pictures of combing in action are available from the Metalab blog at:<br> +<a href="http://reprap.soup.io/?search=combing">http://reprap.soup.io/?search=combing</a><br> <br> <br> > python comb.py<br> @@ -71,15 +76,16 @@ many lines of 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 lines of 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 a gcode thread to the output.</tt></dd></dl> + <dl><dt><a name="CombSkein-addGcodeMovement"><strong>addGcodeMovement</strong></a>(self, point)</dt><dd><tt>Add a movement to the output.</tt></dd></dl> <dl><dt><a name="CombSkein-addIfTravel"><strong>addIfTravel</strong></a>(self, splitLine)</dt><dd><tt>Add travel move around loops if this the extruder is off.</tt></dd></dl> <dl><dt><a name="CombSkein-addLine"><strong>addLine</strong></a>(self, line)</dt><dd><tt>Add a line of text and a newline to the output.</tt></dd></dl> +<dl><dt><a name="CombSkein-addPathBeforeEnd"><strong>addPathBeforeEnd</strong></a>(self, loop)</dt><dd><tt>Add the path before the end of the loop.</tt></dd></dl> + <dl><dt><a name="CombSkein-addPathBetween"><strong>addPathBetween</strong></a>(self, betweenFirst, betweenSecond, loopFirst)</dt><dd><tt>Add a path between the perimeter and the fill.</tt></dd></dl> +<dl><dt><a name="CombSkein-addTailoredLoopPath"><strong>addTailoredLoopPath</strong></a>(self)</dt><dd><tt>Add a clipped and jittered loop path.</tt></dd></dl> + <dl><dt><a name="CombSkein-addToLoop"><strong>addToLoop</strong></a>(self, location)</dt><dd><tt>Add a location to loop.</tt></dd></dl> <dl><dt><a name="CombSkein-getBetweens"><strong>getBetweens</strong></a>(self)</dt><dd><tt>Set betweens for the layer.</tt></dd></dl> +<dl><dt><a name="CombSkein-getJitteredLoop"><strong>getJitteredLoop</strong></a>(self, jitterDistance, jitterLoop)</dt><dd><tt>Get a jittered loop path.</tt></dd></dl> + <dl><dt><a name="CombSkein-getOutloopLocation"><strong>getOutloopLocation</strong></a>(self, point)</dt><dd><tt>Get location outside of loop.</tt></dd></dl> <dl><dt><a name="CombSkein-getRounded"><strong>getRounded</strong></a>(self, number)</dt><dd><tt>Get number rounded to the number of carried decimal places as a string.</tt></dd></dl> +<dl><dt><a name="CombSkein-initializeMoreParameters"><strong>initializeMoreParameters</strong></a>(self)</dt><dd><tt>Add a movement to the output.</tt></dd></dl> + +<dl><dt><a name="CombSkein-insertPathsAroundBetween"><strong>insertPathsAroundBetween</strong></a>(self, location)</dt><dd><tt>Insert paths around and between the perimeter and the fill.</tt></dd></dl> + <dl><dt><a name="CombSkein-insertPathsBetween"><strong>insertPathsBetween</strong></a>(self, nextBeginning, pathEnd)</dt><dd><tt>Insert paths between the perimeter and the fill.</tt></dd></dl> +<dl><dt><a name="CombSkein-isClose"><strong>isClose</strong></a>(self, locationFirst, locationSecond)</dt><dd><tt>Determine if the first location is close to the second location.</tt></dd></dl> + +<dl><dt><a name="CombSkein-isNextExtruderOn"><strong>isNextExtruderOn</strong></a>(self)</dt><dd><tt>Determine if there is an extruder on command before a move command.</tt></dd></dl> + +<dl><dt><a name="CombSkein-linearMove"><strong>linearMove</strong></a>(self, splitLine)</dt><dd><tt>Add to loop path if this is a loop or path.</tt></dd></dl> + +<dl><dt><a name="CombSkein-parseAddJitter"><strong>parseAddJitter</strong></a>(self, line)</dt><dd><tt>Parse a gcode line, jitter it and add it to the comb skein.</tt></dd></dl> + <dl><dt><a name="CombSkein-parseAddTravel"><strong>parseAddTravel</strong></a>(self, line)</dt><dd><tt>Parse a gcode line and add it to the comb skein.</tt></dd></dl> -<dl><dt><a name="CombSkein-parseGcode"><strong>parseGcode</strong></a>(self, gcodeText)</dt><dd><tt>Parse gcode text and store the comb gcode.</tt></dd></dl> +<dl><dt><a name="CombSkein-parseGcode"><strong>parseGcode</strong></a>(self, combPreferences, gcodeText)</dt><dd><tt>Parse gcode text and store the comb gcode.</tt></dd></dl> + +<dl><dt><a name="CombSkein-parseInitialization"><strong>parseInitialization</strong></a>(self, combPreferences)</dt><dd><tt>Parse gcode initialization and store the parameters.</tt></dd></dl> -<dl><dt><a name="CombSkein-parseLine"><strong>parseLine</strong></a>(self, line)</dt><dd><tt>Parse a gcode line.</tt></dd></dl> +<dl><dt><a name="CombSkein-parseLine"><strong>parseLine</strong></a>(self, combPreferences, line)</dt><dd><tt>Parse a gcode 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 is a script to raise the extruder when it is not extruding.<br> <br> -The default 'Activate Hop' checkbox is on. When it is on, the functions described below will work, when it is off, the functions<br> -will not be called.<br> +The default 'Activate Hop' checkbox is off. It is off because Vik and Nophead found better results without hopping. When it<br> +is on, the functions described below will work, when it is off, the functions will not be called.<br> <br> The important value for the hop preferences is "Hop Over Extrusion Height (ratio)" which is the ratio of the hop height over the<br> extrusion height, the default is 1.0. The 'Minimum Hop Angle (degrees)' is the minimum angle that the path of the 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> </tt></td><td> </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> (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> (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> (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> (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 line of nozzle wiped gcode.</tt></p> <font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr> <tr><td bgcolor="#eeaa77"><tt> </tt></td><td> </td> -<td width="100%"><dl><dt><a name="-getIntermediateLocation"><strong>getIntermediateLocation</strong></a>(alongWay, begin, end)</dt><dd><tt>Get the intermediate location between begin and 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 wipe a gcode linear move text. Chain nozzle wipe the gcode if it is not already nozzle 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 wipe a gcode linear move text. Chain nozzle wipe the gcode if it is not already nozzle wiped.</tt></dd></dl> <dl><dt><a name="-getNozzleWipeGcode"><strong>getNozzleWipeGcode</strong></a>(gcodeText, nozzleWipePreferences<font color="#909090">=None</font>)</dt><dd><tt>Nozzle wipe a gcode linear move text.</tt></dd></dl> <dl><dt><a name="-main"><strong>main</strong></a>(hashtable<font color="#909090">=None</font>)</dt><dd><tt>Display the nozzle wipe dialog.</tt></dd></dl> <dl><dt><a name="-writeOutput"><strong>writeOutput</strong></a>(filename<font color="#909090">=''</font>)</dt><dd><tt>Nozzle wipe a gcode linear move file. Chain nozzle wipe the gcode if it is not already nozzle wiped. If no filename is specified, nozzle wipe the first unmodified gcode file in this 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 following examples raft the files Hollow which contains Hollow Square.gcode, Hollow Square.gts and raft.py. The raft function will raft if<br> "Activate Raft, Elevate Nozzle, Orbit and Set Altitude" is true, which can be set in the dialog or by changing the preferences file<br> 'raft.csv' with a text editor or a spreadsheet program set to separate tabs. The functions writeOutput and getRaftChainGcode<br> -check to see if the text has been rafted, if not they call getCombChainGcode in comb.py to get combed gcode; once they have<br> -the combed text, then they raft.<br> +check to see if the text has been rafted, if not they call getClipChainGcode in clip.py to get clipped gcode; once they have<br> +the clipped text, then they raft. Pictures of rafting in action are available from the Metalab blog at:<br> +<a href="http://reprap.soup.io/?search=rafting">http://reprap.soup.io/?search=rafting</a><br> <br> <br> > python raft.py<br> @@ -124,7 +125,7 @@ many lines of 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 -- Vec3 whose angle will be subtractVec3 -- Vec3 whose angle will be subtracted</tt></dd></dl> <dl><dt><a name="-getAroundLoop"><strong>getAroundLoop</strong></a>(begin, end, loop)</dt><dd><tt>Get an arc around a loop.</tt></dd></dl> <dl><dt><a name="-getAwayPath"><strong>getAwayPath</strong></a>(path, radius)</dt><dd><tt>Get a loop with only the points that are far enough away from each other.</tt></dd></dl> + <dl><dt><a name="-getClippedLoopPath"><strong>getClippedLoopPath</strong></a>(clip, loopPath)</dt><dd><tt>Get a clipped loop path.</tt></dd></dl> <dl><dt><a name="-getComplexCrossProduct"><strong>getComplexCrossProduct</strong></a>(firstComplex, secondComplex)</dt><dd><tt>Get z component cross product of a pair of complexes.</tt></dd></dl> <dl><dt><a name="-getComplexDot"><strong>getComplexDot</strong></a>(firstComplex, secondComplex)</dt><dd><tt>Get the dot product of a pair of complexes.</tt></dd></dl> <dl><dt><a name="-getComplexMaximum"><strong>getComplexMaximum</strong></a>(firstComplex, secondComplex)</dt><dd><tt>Get a complex with each component the maximum of the respective components of a pair of complexes.</tt></dd></dl> @@ -147,7 +148,9 @@ subtractVec3 -- Vec3 whose angle will be subt <dl><dt><a name="-getHalfSimplifiedLoop"><strong>getHalfSimplifiedLoop</strong></a>(loop, radius, remainder)</dt><dd><tt>Get the loop with half of the points inside the channel removed.</tt></dd></dl> <dl><dt><a name="-getHalfSimplifiedPath"><strong>getHalfSimplifiedPath</strong></a>(path, radius, remainder)</dt><dd><tt>Get the path with half of the points inside the channel removed.</tt></dd></dl> <dl><dt><a name="-getInsidesAddToOutsides"><strong>getInsidesAddToOutsides</strong></a>(loops, outsides)</dt><dd><tt>Add loops to either the insides or outsides.</tt></dd></dl> + <dl><dt><a name="-getIntermediateLocation"><strong>getIntermediateLocation</strong></a>(alongWay, begin, end)</dt><dd><tt>Get the intermediate location between begin and end.</tt></dd></dl> <dl><dt><a name="-getLeftPoint"><strong>getLeftPoint</strong></a>(path)</dt><dd><tt>Get the leftmost point in the path.</tt></dd></dl> + <dl><dt><a name="-getLoopStartingNearest"><strong>getLoopStartingNearest</strong></a>(extrusionHalfWidthSquared, location, loop)</dt><dd><tt>Add to threads from the last location from loop.</tt></dd></dl> <dl><dt><a name="-getMaximumSpan"><strong>getMaximumSpan</strong></a>(loop)</dt><dd><tt>Get the maximum span in the xy plane.</tt></dd></dl> <dl><dt><a name="-getNearestDistanceSquaredIndex"><strong>getNearestDistanceSquaredIndex</strong></a>(point, loop)</dt><dd><tt>Get the distance squared to the nearest segment of the loop and index of that segment.</tt></dd></dl> <dl><dt><a name="-getNearestPathDistanceSquaredIndex"><strong>getNearestPathDistanceSquaredIndex</strong></a>(point, path)</dt><dd><tt>Get the distance squared to the nearest segment of the path and index of that segment.</tt></dd></dl> @@ -211,6 +214,7 @@ vector3 - Vec3 whose rotation will be returne <dl><dt><a name="-isInsideOtherLoops"><strong>isInsideOtherLoops</strong></a>(loopIndex, loops)</dt><dd><tt>Determine if a loop in a list is inside another loop in that list.</tt></dd></dl> <dl><dt><a name="-isLargeSameDirection"><strong>isLargeSameDirection</strong></a>(inset, loop, requiredSize)</dt><dd><tt>Determine if the inset is in the same direction as the loop and if the inset is as large as the required size.</tt></dd></dl> <dl><dt><a name="-isLineIntersectingInsideXSegment"><strong>isLineIntersectingInsideXSegment</strong></a>(segmentFirstX, segmentSecondX, vector3First, vector3Second, y)</dt><dd><tt>Determine if the line is crossing inside the x segment.</tt></dd></dl> + <dl><dt><a name="-isLineIntersectingLoops"><strong>isLineIntersectingLoops</strong></a>(loops, pointBegin, pointEnd)</dt><dd><tt>Determine if the line is intersecting loops.</tt></dd></dl> <dl><dt><a name="-isLoopIntersectingInsideXSegment"><strong>isLoopIntersectingInsideXSegment</strong></a>(loop, segmentFirstX, segmentSecondX, segmentYMirror, y)</dt><dd><tt>Determine if the loop is intersecting inside the x segment.</tt></dd></dl> <dl><dt><a name="-isLoopIntersectingLoops"><strong>isLoopIntersectingLoops</strong></a>(loop, otherLoops)</dt><dd><tt>Determine if the loop is intersecting other loops.</tt></dd></dl> <dl><dt><a name="-isLoopListIntersectingInsideXSegment"><strong>isLoopListIntersectingInsideXSegment</strong></a>(loopList, segmentFirstX, segmentSecondX, segmentYMirror, y)</dt><dd><tt>Determine if the loop list is crossing inside the x 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 loop inset from clockwise triple, out from widdershins loop.</tt></dd></dl> <dl><dt><a name="-getIntersectionAtInset"><strong>getIntersectionAtInset</strong></a>(ahead, behind, inset)</dt><dd><tt>Get circle intersection loop at inset from segment.</tt></dd></dl> <dl><dt><a name="-getLoopsFromLoopsDirection"><strong>getLoopsFromLoopsDirection</strong></a>(isWiddershins, loops)</dt><dd><tt>Get the loops going round in a given direction.</tt></dd></dl> + <dl><dt><a name="-getSimplifiedInsetFromClockwiseLoop"><strong>getSimplifiedInsetFromClockwiseLoop</strong></a>(loop, radius)</dt><dd><tt>Get loop inset from clockwise loop, out from widdershins loop.</tt></dd></dl> <dl><dt><a name="-getWithoutIntersections"><strong>getWithoutIntersections</strong></a>(loop)</dt><dd><tt>Get loop without intersections.</tt></dd></dl> <dl><dt><a name="-isLoopIntersectingLoop"><strong>isLoopIntersectingLoop</strong></a>(anotherLoop, loop)</dt><dd><tt>Determine if the a loop is intersecting another loop.</tt></dd></dl> <dl><dt><a name="-removeIntersection"><strong>removeIntersection</strong></a>(loop)</dt><dd><tt>Get loop without the first 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 lines of GNU Triangulated Surface vertices,&n <dl><dt><a name="SliceSkein-addFromUpperLowerFile"><strong>addFromUpperLowerFile</strong></a>(self, filename)</dt><dd><tt>Add lines of text from the filename or the lowercase filename, if there is no file by the original filename in the directory.</tt></dd></dl> -<dl><dt><a name="SliceSkein-addGcodeFromPerimeterPaths"><strong>addGcodeFromPerimeterPaths</strong></a>(self, loop, loopLists, radius)</dt><dd><tt>Add the perimeter paths to the output.</tt></dd></dl> +<dl><dt><a name="SliceSkein-addGcodeFromPerimeterPaths"><strong>addGcodeFromPerimeterPaths</strong></a>(self, isIntersectingSelf, loop, loopLists, radius)</dt><dd><tt>Add the perimeter paths to the output.</tt></dd></dl> <dl><dt><a name="SliceSkein-addGcodeFromRemainingLoop"><strong>addGcodeFromRemainingLoop</strong></a>(self, loop, loopLists, radius)</dt><dd><tt>Add the remainder of the loop which does not overlap the alreadyFilledArounds loops.</tt></dd></dl> @@ -169,6 +169,7 @@ many lines of GNU Triangulated Surface vertices,&n <td width="100%"><dl><dt><a name="-addAlreadyFilledArounds"><strong>addAlreadyFilledArounds</strong></a>(alreadyFilledArounds, loop, radius)</dt><dd><tt>Add already filled loops around loop to alreadyFilledArounds.</tt></dd></dl> <dl><dt><a name="-addEdgePair"><strong>addEdgePair</strong></a>(edgePairTable, edges, faceEdgeIndex, remainingEdgeIndex, remainingEdgeTable)</dt><dd><tt>Add edge pair to the edge pair table.</tt></dd></dl> <dl><dt><a name="-addPointsAtZ"><strong>addPointsAtZ</strong></a>(edgePair, points, radius, vertices, z)</dt><dd><tt>Add points on the segment between the edge intersections with z.</tt></dd></dl> + <dl><dt><a name="-addSegmentOutline"><strong>addSegmentOutline</strong></a>(isThick, outlines, pointBegin, pointEnd, width)</dt><dd><tt>Add a diamond or hexagonal outline for a line segment.</tt></dd></dl> <dl><dt><a name="-getCommonVertexIndex"><strong>getCommonVertexIndex</strong></a>(edgeFirst, edgeSecond)</dt><dd><tt>Get the vertex index that both edges have in common.</tt></dd></dl> <dl><dt><a name="-getDoubledRoundZ"><strong>getDoubledRoundZ</strong></a>(overhangingSegment, segmentRoundZ)</dt><dd><tt>Get doubled plane angle around z of the overhanging segment.</tt></dd></dl> <dl><dt><a name="-getLoopsFromCorrectMesh"><strong>getLoopsFromCorrectMesh</strong></a>(edges, faces, vertices, z)</dt><dd><tt>Get loops from a slice of a correct mesh.</tt></dd></dl> @@ -179,11 +180,12 @@ many lines of GNU Triangulated Surface vertices,&n <dl><dt><a name="-getPath"><strong>getPath</strong></a>(edges, pathIndexes, loop, z)</dt><dd><tt>Get the path from the edge intersections.</tt></dd></dl> <dl><dt><a name="-getPathIndexesAddPath"><strong>getPathIndexesAddPath</strong></a>(edges, faces, loops, remainingEdgeTable, vertices, z)</dt><dd><tt>Get the path indexes around a triangle mesh slice and add the path to the loops.</tt></dd></dl> <dl><dt><a name="-getRemainingEdgeTable"><strong>getRemainingEdgeTable</strong></a>(edges, vertices, z)</dt><dd><tt>Get the remaining edge hashtable.</tt></dd></dl> - <dl><dt><a name="-getSegmentsFromPoints"><strong>getSegmentsFromPoints</strong></a>(loopLists, pointBegin, pointEnd)</dt><dd><tt>Get enpoint segments from the beginning and end of a line segment.</tt></dd></dl> + <dl><dt><a name="-getSegmentsFromPoints"><strong>getSegmentsFromPoints</strong></a>(loopLists, pointBegin, pointEnd)</dt><dd><tt>Get endpoint segments from the beginning and end of a line segment.</tt></dd></dl> <dl><dt><a name="-getSharedFace"><strong>getSharedFace</strong></a>(firstEdge, faces, secondEdge)</dt><dd><tt>Get the face which is shared by two edges.</tt></dd></dl> <dl><dt><a name="-getSliceGcode"><strong>getSliceGcode</strong></a>(filename, slicePreferences<font color="#909090">=None</font>)</dt><dd><tt>Slice a shape file.</tt></dd></dl> <dl><dt><a name="-getSliceIntersectionFromEdge"><strong>getSliceIntersectionFromEdge</strong></a>(edge, loop, z)</dt><dd><tt>Get the point where the slice intersects the edge.</tt></dd></dl> <dl><dt><a name="-isCloseToLast"><strong>isCloseToLast</strong></a>(paths, point, radius)</dt><dd><tt>Determine if the point is close to the last point of the last path.</tt></dd></dl> + <dl><dt><a name="-isIntersectingItself"><strong>isIntersectingItself</strong></a>(loop, width)</dt><dd><tt>Determine if the loop is intersecting itself.</tt></dd></dl> <dl><dt><a name="-isIntersectingWithinList"><strong>isIntersectingWithinList</strong></a>(loop, loopList)</dt><dd><tt>Determine if the loop is intersecting or is within the loop list.</tt></dd></dl> <dl><dt><a name="-isIntersectingWithinLists"><strong>isIntersectingWithinLists</strong></a>(loop, loopLists)</dt><dd><tt>Determine if the loop is intersecting or is within the loop lists.</tt></dd></dl> <dl><dt><a name="-isZInEdge"><strong>isZInEdge</strong></a>(edge, vertices, z)</dt><dd><tt>Determine if z is inside the 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 following examples tower the files Hollow  which contains Hollow Square.gcode, Hollow Square.gts and tower.py. The tower function will tower if 'Maximum Tower Layers' is<br> 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<br> program set to separate tabs. The functions writeOutput and getTowerChainGcode check to see if the text has been towered,<br> -if not they call the getFillChainGcode in fill.py to fill the text; once they have the filled text, then they tower.<br> +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<br> +action are available from the Metalab blog at:<br> +<a href="http://reprap.soup.io/?search=towering">http://reprap.soup.io/?search=towering</a><br> <br> <br> > python 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 |